12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715 |
- // ASFormatter.cpp
- // Copyright (c) 2017 by Jim Pattee <jimp03@email.com>.
- // This code is licensed under the MIT License.
- // License.md describes the conditions under which this software may be distributed.
- //-----------------------------------------------------------------------------
- // headers
- //-----------------------------------------------------------------------------
- #include "astyle.h"
- #include <algorithm>
- #include <fstream>
- //-----------------------------------------------------------------------------
- // astyle namespace
- //-----------------------------------------------------------------------------
- namespace astyle {
- //
- //-----------------------------------------------------------------------------
- // ASFormatter class
- //-----------------------------------------------------------------------------
- /**
- * Constructor of ASFormatter
- */
- ASFormatter::ASFormatter()
- {
- sourceIterator = nullptr;
- enhancer = new ASEnhancer;
- preBraceHeaderStack = nullptr;
- braceTypeStack = nullptr;
- parenStack = nullptr;
- structStack = nullptr;
- questionMarkStack = nullptr;
- lineCommentNoIndent = false;
- formattingStyle = STYLE_NONE;
- braceFormatMode = NONE_MODE;
- pointerAlignment = PTR_ALIGN_NONE;
- referenceAlignment = REF_SAME_AS_PTR;
- objCColonPadMode = COLON_PAD_NO_CHANGE;
- lineEnd = LINEEND_DEFAULT;
- maxCodeLength = string::npos;
- shouldPadCommas = false;
- shouldPadOperators = false;
- shouldPadParensOutside = false;
- shouldPadFirstParen = false;
- shouldPadParensInside = false;
- shouldPadHeader = false;
- shouldStripCommentPrefix = false;
- shouldUnPadParens = false;
- attachClosingBraceMode = false;
- shouldBreakOneLineBlocks = true;
- shouldBreakOneLineHeaders = false;
- shouldBreakOneLineStatements = true;
- shouldConvertTabs = false;
- shouldIndentCol1Comments = false;
- shouldIndentPreprocBlock = false;
- shouldCloseTemplates = false;
- shouldAttachExternC = false;
- shouldAttachNamespace = false;
- shouldAttachClass = false;
- shouldAttachClosingWhile = false;
- shouldAttachInline = false;
- shouldBreakBlocks = false;
- shouldBreakClosingHeaderBlocks = false;
- shouldBreakClosingHeaderBraces = false;
- shouldDeleteEmptyLines = false;
- shouldBreakElseIfs = false;
- shouldBreakLineAfterLogical = false;
- shouldAddBraces = false;
- shouldAddOneLineBraces = false;
- shouldRemoveBraces = false;
- shouldPadMethodColon = false;
- shouldPadMethodPrefix = false;
- shouldUnPadMethodPrefix = false;
- shouldPadReturnType = false;
- shouldUnPadReturnType = false;
- shouldPadParamType = false;
- shouldUnPadParamType = false;
- // initialize ASFormatter member vectors
- formatterFileType = 9; // reset to an invalid type
- headers = new vector<const string*>;
- nonParenHeaders = new vector<const string*>;
- preDefinitionHeaders = new vector<const string*>;
- preCommandHeaders = new vector<const string*>;
- operators = new vector<const string*>;
- assignmentOperators = new vector<const string*>;
- castOperators = new vector<const string*>;
- // initialize ASEnhancer member vectors
- indentableMacros = new vector<const pair<const string, const string>* >;
- }
- /**
- * Destructor of ASFormatter
- */
- ASFormatter::~ASFormatter()
- {
- // delete ASFormatter stack vectors
- deleteContainer(preBraceHeaderStack);
- deleteContainer(braceTypeStack);
- deleteContainer(parenStack);
- deleteContainer(structStack);
- deleteContainer(questionMarkStack);
- // delete ASFormatter member vectors
- formatterFileType = 9; // reset to an invalid type
- delete headers;
- delete nonParenHeaders;
- delete preDefinitionHeaders;
- delete preCommandHeaders;
- delete operators;
- delete assignmentOperators;
- delete castOperators;
- // delete ASEnhancer member vectors
- delete indentableMacros;
- // must be done when the ASFormatter object is deleted (not ASBeautifier)
- // delete ASBeautifier member vectors
- ASBeautifier::deleteBeautifierVectors();
- delete enhancer;
- }
- /**
- * initialize the ASFormatter.
- *
- * init() should be called every time a ASFormatter object is to start
- * formatting a NEW source file.
- * init() receives a pointer to a ASSourceIterator object that will be
- * used to iterate through the source code.
- *
- * @param si a pointer to the ASSourceIterator or ASStreamIterator object.
- */
- void ASFormatter::init(ASSourceIterator* si)
- {
- buildLanguageVectors();
- fixOptionVariableConflicts();
- ASBeautifier::init(si);
- sourceIterator = si;
- enhancer->init(getFileType(),
- getIndentLength(),
- getTabLength(),
- getIndentString() == "\t",
- getForceTabIndentation(),
- getNamespaceIndent(),
- getCaseIndent(),
- shouldIndentPreprocBlock,
- getPreprocDefineIndent(),
- getEmptyLineFill(),
- indentableMacros);
- initContainer(preBraceHeaderStack, new vector<const string*>);
- initContainer(parenStack, new vector<int>);
- initContainer(structStack, new vector<bool>);
- initContainer(questionMarkStack, new vector<bool>);
- parenStack->emplace_back(0); // parenStack must contain this default entry
- initContainer(braceTypeStack, new vector<BraceType>);
- braceTypeStack->emplace_back(NULL_TYPE); // braceTypeStack must contain this default entry
- clearFormattedLineSplitPoints();
- currentHeader = nullptr;
- currentLine = "";
- readyFormattedLine = "";
- formattedLine = "";
- verbatimDelimiter = "";
- currentChar = ' ';
- previousChar = ' ';
- previousCommandChar = ' ';
- previousNonWSChar = ' ';
- quoteChar = '"';
- preprocBlockEnd = 0;
- charNum = 0;
- checksumIn = 0;
- checksumOut = 0;
- currentLineFirstBraceNum = string::npos;
- formattedLineCommentNum = 0;
- leadingSpaces = 0;
- previousReadyFormattedLineLength = string::npos;
- preprocBraceTypeStackSize = 0;
- spacePadNum = 0;
- nextLineSpacePadNum = 0;
- objCColonAlign = 0;
- templateDepth = 0;
- squareBracketCount = 0;
- runInIndentChars = 0;
- tabIncrementIn = 0;
- previousBraceType = NULL_TYPE;
- isVirgin = true;
- isInVirginLine = true;
- isInLineComment = false;
- isInComment = false;
- isInCommentStartLine = false;
- noTrimCommentContinuation = false;
- isInPreprocessor = false;
- isInPreprocessorBeautify = false;
- doesLineStartComment = false;
- lineEndsInCommentOnly = false;
- lineIsCommentOnly = false;
- lineIsLineCommentOnly = false;
- lineIsEmpty = false;
- isImmediatelyPostCommentOnly = false;
- isImmediatelyPostEmptyLine = false;
- isInClassInitializer = false;
- isInQuote = false;
- isInVerbatimQuote = false;
- haveLineContinuationChar = false;
- isInQuoteContinuation = false;
- isHeaderInMultiStatementLine = false;
- isSpecialChar = false;
- isNonParenHeader = false;
- foundNamespaceHeader = false;
- foundClassHeader = false;
- foundStructHeader = false;
- foundInterfaceHeader = false;
- foundPreDefinitionHeader = false;
- foundPreCommandHeader = false;
- foundPreCommandMacro = false;
- foundTrailingReturnType = false;
- foundCastOperator = false;
- foundQuestionMark = false;
- isInLineBreak = false;
- endOfAsmReached = false;
- endOfCodeReached = false;
- isFormattingModeOff = false;
- isInEnum = false;
- isInExecSQL = false;
- isInAsm = false;
- isInAsmOneLine = false;
- isInAsmBlock = false;
- isLineReady = false;
- elseHeaderFollowsComments = false;
- caseHeaderFollowsComments = false;
- isPreviousBraceBlockRelated = false;
- isInPotentialCalculation = false;
- needHeaderOpeningBrace = false;
- shouldBreakLineAtNextChar = false;
- shouldKeepLineUnbroken = false;
- shouldReparseCurrentChar = false;
- passedSemicolon = false;
- passedColon = false;
- isImmediatelyPostNonInStmt = false;
- isCharImmediatelyPostNonInStmt = false;
- isInTemplate = false;
- isImmediatelyPostComment = false;
- isImmediatelyPostLineComment = false;
- isImmediatelyPostEmptyBlock = false;
- isImmediatelyPostObjCMethodPrefix = false;
- isImmediatelyPostPreprocessor = false;
- isImmediatelyPostReturn = false;
- isImmediatelyPostThrow = false;
- isImmediatelyPostNewDelete = false;
- isImmediatelyPostOperator = false;
- isImmediatelyPostTemplate = false;
- isImmediatelyPostPointerOrReference = false;
- isCharImmediatelyPostReturn = false;
- isCharImmediatelyPostThrow = false;
- isCharImmediatelyPostNewDelete = false;
- isCharImmediatelyPostOperator = false;
- isCharImmediatelyPostComment = false;
- isPreviousCharPostComment = false;
- isCharImmediatelyPostLineComment = false;
- isCharImmediatelyPostOpenBlock = false;
- isCharImmediatelyPostCloseBlock = false;
- isCharImmediatelyPostTemplate = false;
- isCharImmediatelyPostPointerOrReference = false;
- isInObjCInterface = false;
- isInObjCMethodDefinition = false;
- isInObjCReturnType = false;
- isInObjCSelector = false;
- breakCurrentOneLineBlock = false;
- shouldRemoveNextClosingBrace = false;
- isInBraceRunIn = false;
- currentLineBeginsWithBrace = false;
- isPrependPostBlockEmptyLineRequested = false;
- isAppendPostBlockEmptyLineRequested = false;
- isIndentableProprocessor = false;
- isIndentableProprocessorBlock = false;
- prependEmptyLine = false;
- appendOpeningBrace = false;
- foundClosingHeader = false;
- isImmediatelyPostHeader = false;
- isInHeader = false;
- isInCase = false;
- isFirstPreprocConditional = false;
- processedFirstConditional = false;
- isJavaStaticConstructor = false;
- }
- /**
- * build vectors for each programing language
- * depending on the file extension.
- */
- void ASFormatter::buildLanguageVectors()
- {
- if (getFileType() == formatterFileType) // don't build unless necessary
- return;
- formatterFileType = getFileType();
- headers->clear();
- nonParenHeaders->clear();
- preDefinitionHeaders->clear();
- preCommandHeaders->clear();
- operators->clear();
- assignmentOperators->clear();
- castOperators->clear();
- indentableMacros->clear(); // ASEnhancer
- ASResource::buildHeaders(headers, getFileType());
- ASResource::buildNonParenHeaders(nonParenHeaders, getFileType());
- ASResource::buildPreDefinitionHeaders(preDefinitionHeaders, getFileType());
- ASResource::buildPreCommandHeaders(preCommandHeaders, getFileType());
- ASResource::buildOperators(operators, getFileType());
- ASResource::buildAssignmentOperators(assignmentOperators);
- ASResource::buildCastOperators(castOperators);
- ASResource::buildIndentableMacros(indentableMacros); //ASEnhancer
- }
- /**
- * set the variables for each predefined style.
- * this will override any previous settings.
- */
- void ASFormatter::fixOptionVariableConflicts()
- {
- if (formattingStyle == STYLE_ALLMAN)
- {
- setBraceFormatMode(BREAK_MODE);
- }
- else if (formattingStyle == STYLE_JAVA)
- {
- setBraceFormatMode(ATTACH_MODE);
- }
- else if (formattingStyle == STYLE_KR)
- {
- setBraceFormatMode(LINUX_MODE);
- }
- else if (formattingStyle == STYLE_STROUSTRUP)
- {
- setBraceFormatMode(LINUX_MODE);
- setBreakClosingHeaderBracesMode(true);
- }
- else if (formattingStyle == STYLE_WHITESMITH)
- {
- setBraceFormatMode(BREAK_MODE);
- setBraceIndent(true);
- setClassIndent(true); // avoid hanging indent with access modifiers
- setSwitchIndent(true); // avoid hanging indent with case statements
- }
- else if (formattingStyle == STYLE_VTK)
- {
- // the unindented class brace does NOT cause a hanging indent like Whitesmith
- setBraceFormatMode(BREAK_MODE);
- setBraceIndentVtk(true); // sets both braceIndent and braceIndentVtk
- setSwitchIndent(true); // avoid hanging indent with case statements
- }
- else if (formattingStyle == STYLE_BANNER)
- {
- // attached braces can have hanging indents with the closing brace
- setBraceFormatMode(ATTACH_MODE);
- setBraceIndent(true);
- setClassIndent(true); // avoid hanging indent with access modifiers
- setSwitchIndent(true); // avoid hanging indent with case statements
- }
- else if (formattingStyle == STYLE_GNU)
- {
- setBraceFormatMode(BREAK_MODE);
- setBlockIndent(true);
- }
- else if (formattingStyle == STYLE_LINUX)
- {
- setBraceFormatMode(LINUX_MODE);
- // always for Linux style
- setMinConditionalIndentOption(MINCOND_ONEHALF);
- }
- else if (formattingStyle == STYLE_HORSTMANN)
- {
- setBraceFormatMode(RUN_IN_MODE);
- setSwitchIndent(true);
- }
- else if (formattingStyle == STYLE_1TBS)
- {
- setBraceFormatMode(LINUX_MODE);
- setAddBracesMode(true);
- setRemoveBracesMode(false);
- }
- else if (formattingStyle == STYLE_GOOGLE)
- {
- setBraceFormatMode(ATTACH_MODE);
- setModifierIndent(true);
- setClassIndent(false);
- }
- else if (formattingStyle == STYLE_MOZILLA)
- {
- setBraceFormatMode(LINUX_MODE);
- }
- else if (formattingStyle == STYLE_PICO)
- {
- setBraceFormatMode(RUN_IN_MODE);
- setAttachClosingBraceMode(true);
- setSwitchIndent(true);
- setBreakOneLineBlocksMode(false);
- setBreakOneLineStatementsMode(false);
- // add-braces won't work for pico, but it could be fixed if necessary
- // both options should be set to true
- if (shouldAddBraces)
- shouldAddOneLineBraces = true;
- }
- else if (formattingStyle == STYLE_LISP)
- {
- setBraceFormatMode(ATTACH_MODE);
- setAttachClosingBraceMode(true);
- setBreakOneLineStatementsMode(false);
- // add-one-line-braces won't work for lisp
- // only shouldAddBraces should be set to true
- if (shouldAddOneLineBraces)
- {
- shouldAddBraces = true;
- shouldAddOneLineBraces = false;
- }
- }
- setMinConditionalIndentLength();
- // if not set by indent=force-tab-x set equal to indentLength
- if (getTabLength() == 0)
- setDefaultTabLength();
- // add-one-line-braces implies keep-one-line-blocks
- if (shouldAddOneLineBraces)
- setBreakOneLineBlocksMode(false);
- // don't allow add-braces and remove-braces
- if (shouldAddBraces || shouldAddOneLineBraces)
- setRemoveBracesMode(false);
- // don't allow indent-classes and indent-modifiers
- if (getClassIndent())
- setModifierIndent(false);
- }
- /**
- * get the next formatted line.
- *
- * @return formatted line.
- */
- string ASFormatter::nextLine()
- {
- const string* newHeader = nullptr;
- isInVirginLine = isVirgin;
- isCharImmediatelyPostComment = false;
- isPreviousCharPostComment = false;
- isCharImmediatelyPostLineComment = false;
- isCharImmediatelyPostOpenBlock = false;
- isCharImmediatelyPostCloseBlock = false;
- isCharImmediatelyPostTemplate = false;
- while (!isLineReady)
- {
- if (shouldReparseCurrentChar)
- shouldReparseCurrentChar = false;
- else if (!getNextChar())
- {
- breakLine();
- continue;
- }
- else // stuff to do when reading a new character...
- {
- // make sure that a virgin '{' at the beginning of the file will be treated as a block...
- if (isInVirginLine && currentChar == '{'
- && currentLineBeginsWithBrace
- && previousCommandChar == ' ')
- previousCommandChar = '{';
- if (isInClassInitializer
- && isBraceType(braceTypeStack->back(), COMMAND_TYPE))
- isInClassInitializer = false;
- if (isInBraceRunIn)
- isInLineBreak = false;
- if (!isWhiteSpace(currentChar))
- isInBraceRunIn = false;
- isPreviousCharPostComment = isCharImmediatelyPostComment;
- isCharImmediatelyPostComment = false;
- isCharImmediatelyPostTemplate = false;
- isCharImmediatelyPostReturn = false;
- isCharImmediatelyPostThrow = false;
- isCharImmediatelyPostNewDelete = false;
- isCharImmediatelyPostOperator = false;
- isCharImmediatelyPostPointerOrReference = false;
- isCharImmediatelyPostOpenBlock = false;
- isCharImmediatelyPostCloseBlock = false;
- }
- if ((lineIsLineCommentOnly || lineIsCommentOnly)
- && currentLine.find("*INDENT-ON*", charNum) != string::npos
- && isFormattingModeOff)
- {
- isFormattingModeOff = false;
- breakLine();
- formattedLine = currentLine;
- charNum = (int) currentLine.length() - 1;
- continue;
- }
- if (isFormattingModeOff)
- {
- breakLine();
- formattedLine = currentLine;
- charNum = (int) currentLine.length() - 1;
- continue;
- }
- if ((lineIsLineCommentOnly || lineIsCommentOnly)
- && currentLine.find("*INDENT-OFF*", charNum) != string::npos)
- {
- isFormattingModeOff = true;
- if (isInLineBreak) // is true if not the first line
- breakLine();
- formattedLine = currentLine;
- charNum = (int)currentLine.length() - 1;
- continue;
- }
- if (shouldBreakLineAtNextChar)
- {
- if (isWhiteSpace(currentChar) && !lineIsEmpty)
- continue;
- isInLineBreak = true;
- shouldBreakLineAtNextChar = false;
- }
- if (isInExecSQL && !passedSemicolon)
- {
- if (currentChar == ';')
- passedSemicolon = true;
- appendCurrentChar();
- continue;
- }
- if (isInLineComment)
- {
- formatLineCommentBody();
- continue;
- }
- else if (isInComment)
- {
- formatCommentBody();
- continue;
- }
- else if (isInQuote)
- {
- formatQuoteBody();
- continue;
- }
- // not in quote or comment or line comment
- if (isSequenceReached("//"))
- {
- formatLineCommentOpener();
- testForTimeToSplitFormattedLine();
- continue;
- }
- else if (isSequenceReached("/*"))
- {
- formatCommentOpener();
- testForTimeToSplitFormattedLine();
- continue;
- }
- else if (currentChar == '"'
- || (currentChar == '\'' && !isDigitSeparator(currentLine, charNum)))
- {
- formatQuoteOpener();
- testForTimeToSplitFormattedLine();
- continue;
- }
- // treat these preprocessor statements as a line comment
- else if (currentChar == '#'
- && currentLine.find_first_not_of(" \t") == (size_t) charNum)
- {
- string preproc = trim(currentLine.c_str() + charNum + 1);
- if (preproc.length() > 0
- && isCharPotentialHeader(preproc, 0)
- && (findKeyword(preproc, 0, "region")
- || findKeyword(preproc, 0, "endregion")
- || findKeyword(preproc, 0, "error")
- || findKeyword(preproc, 0, "warning")
- || findKeyword(preproc, 0, "line")))
- {
- currentLine = rtrim(currentLine); // trim the end only
- // check for run-in
- if (formattedLine.length() > 0 && formattedLine[0] == '{')
- {
- isInLineBreak = true;
- isInBraceRunIn = false;
- }
- if (previousCommandChar == '}')
- currentHeader = nullptr;
- isInLineComment = true;
- appendCurrentChar();
- continue;
- }
- }
- if (isInPreprocessor)
- {
- appendCurrentChar();
- continue;
- }
- if (isInTemplate && shouldCloseTemplates)
- {
- if (previousNonWSChar == '>' && isWhiteSpace(currentChar) && peekNextChar() == '>')
- continue;
- }
- if (shouldRemoveNextClosingBrace && currentChar == '}')
- {
- currentLine[charNum] = currentChar = ' ';
- shouldRemoveNextClosingBrace = false;
- assert(adjustChecksumIn(-'}'));
- if (isEmptyLine(currentLine))
- continue;
- }
- // handle white space - needed to simplify the rest.
- if (isWhiteSpace(currentChar))
- {
- appendCurrentChar();
- continue;
- }
- /* not in MIDDLE of quote or comment or SQL or white-space of any type ... */
- // check if in preprocessor
- // ** isInPreprocessor will be automatically reset at the beginning
- // of a new line in getnextChar()
- if (currentChar == '#')
- {
- isInPreprocessor = true;
- // check for run-in
- if (formattedLine.length() > 0 && formattedLine[0] == '{')
- {
- isInLineBreak = true;
- isInBraceRunIn = false;
- }
- processPreprocessor();
- // if top level it is potentially indentable
- if (shouldIndentPreprocBlock
- && (isBraceType(braceTypeStack->back(), NULL_TYPE)
- || isBraceType(braceTypeStack->back(), NAMESPACE_TYPE))
- && !foundClassHeader
- && !isInClassInitializer
- && sourceIterator->tellg() > preprocBlockEnd)
- {
- // indent the #if preprocessor blocks
- string preproc = ASBeautifier::extractPreprocessorStatement(currentLine);
- if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") // #if, #ifdef, #ifndef
- {
- if (isImmediatelyPostPreprocessor)
- breakLine();
- isIndentableProprocessorBlock = isIndentablePreprocessorBlock(currentLine, charNum);
- isIndentableProprocessor = isIndentableProprocessorBlock;
- }
- }
- if (isIndentableProprocessorBlock
- && charNum < (int) currentLine.length() - 1
- && isWhiteSpace(currentLine[charNum + 1]))
- {
- size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
- if (nextText != string::npos)
- currentLine.erase(charNum + 1, nextText - charNum - 1);
- }
- if (isIndentableProprocessorBlock
- && sourceIterator->tellg() >= preprocBlockEnd)
- isIndentableProprocessorBlock = false;
- // need to fall thru here to reset the variables
- }
- /* not in preprocessor ... */
- if (isImmediatelyPostComment)
- {
- caseHeaderFollowsComments = false;
- isImmediatelyPostComment = false;
- isCharImmediatelyPostComment = true;
- }
- if (isImmediatelyPostLineComment)
- {
- caseHeaderFollowsComments = false;
- isImmediatelyPostLineComment = false;
- isCharImmediatelyPostLineComment = true;
- }
- if (isImmediatelyPostReturn)
- {
- isImmediatelyPostReturn = false;
- isCharImmediatelyPostReturn = true;
- }
- if (isImmediatelyPostThrow)
- {
- isImmediatelyPostThrow = false;
- isCharImmediatelyPostThrow = true;
- }
- if (isImmediatelyPostNewDelete)
- {
- isImmediatelyPostNewDelete = false;
- isCharImmediatelyPostNewDelete = true;
- }
- if (isImmediatelyPostOperator)
- {
- isImmediatelyPostOperator = false;
- isCharImmediatelyPostOperator = true;
- }
- if (isImmediatelyPostTemplate)
- {
- isImmediatelyPostTemplate = false;
- isCharImmediatelyPostTemplate = true;
- }
- if (isImmediatelyPostPointerOrReference)
- {
- isImmediatelyPostPointerOrReference = false;
- isCharImmediatelyPostPointerOrReference = true;
- }
- // reset isImmediatelyPostHeader information
- if (isImmediatelyPostHeader)
- {
- // should braces be added
- if (currentChar != '{'
- && shouldAddBraces
- && (shouldBreakOneLineStatements || !isHeaderInMultiStatementLine)
- && isOkToBreakBlock(braceTypeStack->back()))
- {
- bool bracesAdded = addBracesToStatement();
- if (bracesAdded && !shouldAddOneLineBraces)
- {
- size_t firstText = currentLine.find_first_not_of(" \t");
- assert(firstText != string::npos);
- if ((int) firstText == charNum || shouldBreakOneLineHeaders)
- breakCurrentOneLineBlock = true;
- }
- }
- // should braces be removed
- else if (currentChar == '{' && shouldRemoveBraces)
- {
- bool bracesRemoved = removeBracesFromStatement();
- if (bracesRemoved)
- {
- shouldRemoveNextClosingBrace = true;
- if (isBeforeAnyLineEndComment(charNum))
- spacePadNum--;
- else if (shouldBreakOneLineBlocks
- || (currentLineBeginsWithBrace
- && currentLine.find_first_not_of(" \t") != string::npos))
- shouldBreakLineAtNextChar = true;
- continue;
- }
- }
- // break 'else-if' if shouldBreakElseIfs is requested
- if (shouldBreakElseIfs
- && currentHeader == &AS_ELSE
- && isOkToBreakBlock(braceTypeStack->back())
- && !isBeforeAnyComment()
- && (shouldBreakOneLineStatements || !isHeaderInMultiStatementLine))
- {
- string nextText = peekNextText(currentLine.substr(charNum));
- if (nextText.length() > 0
- && isCharPotentialHeader(nextText, 0)
- && ASBase::findHeader(nextText, 0, headers) == &AS_IF)
- {
- isInLineBreak = true;
- }
- }
- // break a header (e.g. if, while, else) from the following statement
- if (shouldBreakOneLineHeaders
- && peekNextChar() != ' '
- && (shouldBreakOneLineStatements
- || (!isHeaderInMultiStatementLine
- && !isMultiStatementLine()))
- && isOkToBreakBlock(braceTypeStack->back())
- && !isBeforeAnyComment())
- {
- if (currentChar == '{')
- {
- if (!currentLineBeginsWithBrace)
- {
- if (isOneLineBlockReached(currentLine, charNum) == 3)
- isInLineBreak = false;
- else
- breakCurrentOneLineBlock = true;
- }
- }
- else if (currentHeader == &AS_ELSE)
- {
- string nextText = peekNextText(currentLine.substr(charNum), true);
- if (nextText.length() > 0
- && ((isCharPotentialHeader(nextText, 0)
- && ASBase::findHeader(nextText, 0, headers) != &AS_IF)
- || nextText[0] == '{'))
- isInLineBreak = true;
- }
- else
- {
- isInLineBreak = true;
- }
- }
- isImmediatelyPostHeader = false;
- }
- if (passedSemicolon) // need to break the formattedLine
- {
- passedSemicolon = false;
- if (parenStack->back() == 0 && !isCharImmediatelyPostComment && currentChar != ';') // allow ;;
- {
- // does a one-line block have ending comments?
- if (isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE))
- {
- size_t blockEnd = currentLine.rfind(AS_CLOSE_BRACE);
- assert(blockEnd != string::npos);
- // move ending comments to this formattedLine
- if (isBeforeAnyLineEndComment(blockEnd))
- {
- size_t commentStart = currentLine.find_first_not_of(" \t", blockEnd + 1);
- assert(commentStart != string::npos);
- assert((currentLine.compare(commentStart, 2, "//") == 0)
- || (currentLine.compare(commentStart, 2, "/*") == 0));
- formattedLine.append(getIndentLength() - 1, ' ');
- // append comment
- int charNumSave = charNum;
- charNum = commentStart;
- while (charNum < (int) currentLine.length())
- {
- currentChar = currentLine[charNum];
- if (currentChar == '\t' && shouldConvertTabs)
- convertTabToSpaces();
- formattedLine.append(1, currentChar);
- ++charNum;
- }
- size_t commentLength = currentLine.length() - commentStart;
- currentLine.erase(commentStart, commentLength);
- charNum = charNumSave;
- currentChar = currentLine[charNum];
- testForTimeToSplitFormattedLine();
- }
- }
- isInExecSQL = false;
- shouldReparseCurrentChar = true;
- if (formattedLine.find_first_not_of(" \t") != string::npos)
- isInLineBreak = true;
- if (needHeaderOpeningBrace)
- {
- isCharImmediatelyPostCloseBlock = true;
- needHeaderOpeningBrace = false;
- }
- continue;
- }
- }
- if (passedColon)
- {
- passedColon = false;
- if (parenStack->back() == 0
- && !isBeforeAnyComment()
- && (formattedLine.find_first_not_of(" \t") != string::npos))
- {
- shouldReparseCurrentChar = true;
- isInLineBreak = true;
- continue;
- }
- }
- // Check if in template declaration, e.g. foo<bar> or foo<bar,fig>
- if (!isInTemplate && currentChar == '<')
- {
- checkIfTemplateOpener();
- }
- // handle parens
- if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
- {
- questionMarkStack->push_back(foundQuestionMark);
- foundQuestionMark = false;
- parenStack->back()++;
- if (currentChar == '[')
- {
- ++squareBracketCount;
- if (getAlignMethodColon() && squareBracketCount == 1 && isCStyle())
- objCColonAlign = findObjCColonAlignment();
- }
- }
- else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>'))
- {
- foundPreCommandHeader = false;
- parenStack->back()--;
- // this can happen in preprocessor directives
- if (parenStack->back() < 0)
- parenStack->back() = 0;
- if (!questionMarkStack->empty())
- {
- foundQuestionMark = questionMarkStack->back();
- questionMarkStack->pop_back();
- }
- if (isInTemplate && currentChar == '>')
- {
- templateDepth--;
- if (templateDepth == 0)
- {
- isInTemplate = false;
- isImmediatelyPostTemplate = true;
- }
- }
- // check if this parenthesis closes a header, e.g. if (...), while (...)
- if (isInHeader && parenStack->back() == 0)
- {
- isInHeader = false;
- isImmediatelyPostHeader = true;
- foundQuestionMark = false;
- }
- if (currentChar == ']')
- {
- --squareBracketCount;
- if (squareBracketCount <= 0)
- {
- squareBracketCount = 0;
- objCColonAlign = 0;
- }
- }
- if (currentChar == ')')
- {
- foundCastOperator = false;
- if (parenStack->back() == 0)
- endOfAsmReached = true;
- }
- }
- // handle braces
- if (currentChar == '{' || currentChar == '}')
- {
- // if appendOpeningBrace this was already done for the original brace
- if (currentChar == '{' && !appendOpeningBrace)
- {
- BraceType newBraceType = getBraceType();
- breakCurrentOneLineBlock = false;
- foundNamespaceHeader = false;
- foundClassHeader = false;
- foundStructHeader = false;
- foundInterfaceHeader = false;
- foundPreDefinitionHeader = false;
- foundPreCommandHeader = false;
- foundPreCommandMacro = false;
- foundTrailingReturnType = false;
- isInPotentialCalculation = false;
- isInObjCMethodDefinition = false;
- isInObjCInterface = false;
- isInEnum = false;
- isJavaStaticConstructor = false;
- isCharImmediatelyPostNonInStmt = false;
- needHeaderOpeningBrace = false;
- shouldKeepLineUnbroken = false;
- objCColonAlign = 0;
- isPreviousBraceBlockRelated = !isBraceType(newBraceType, ARRAY_TYPE);
- braceTypeStack->emplace_back(newBraceType);
- preBraceHeaderStack->emplace_back(currentHeader);
- currentHeader = nullptr;
- structStack->push_back(isInIndentableStruct);
- if (isBraceType(newBraceType, STRUCT_TYPE) && isCStyle())
- isInIndentableStruct = isStructAccessModified(currentLine, charNum);
- else
- isInIndentableStruct = false;
- }
- // this must be done before the braceTypeStack is popped
- BraceType braceType = braceTypeStack->back();
- bool isOpeningArrayBrace = (isBraceType(braceType, ARRAY_TYPE)
- && braceTypeStack->size() >= 2
- && !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2], ARRAY_TYPE)
- );
- if (currentChar == '}')
- {
- // if a request has been made to append a post block empty line,
- // but the block exists immediately before a closing brace,
- // then there is no need for the post block empty line.
- isAppendPostBlockEmptyLineRequested = false;
- if (isInAsm)
- endOfAsmReached = true;
- isInAsmOneLine = isInQuote = false;
- shouldKeepLineUnbroken = false;
- squareBracketCount = 0;
- if (braceTypeStack->size() > 1)
- {
- previousBraceType = braceTypeStack->back();
- braceTypeStack->pop_back();
- isPreviousBraceBlockRelated = !isBraceType(braceType, ARRAY_TYPE);
- }
- else
- {
- previousBraceType = NULL_TYPE;
- isPreviousBraceBlockRelated = false;
- }
- if (!preBraceHeaderStack->empty())
- {
- currentHeader = preBraceHeaderStack->back();
- preBraceHeaderStack->pop_back();
- }
- else
- currentHeader = nullptr;
- if (!structStack->empty())
- {
- isInIndentableStruct = structStack->back();
- structStack->pop_back();
- }
- else
- isInIndentableStruct = false;
- if (isNonInStatementArray
- && (!isBraceType(braceTypeStack->back(), ARRAY_TYPE) // check previous brace
- || peekNextChar() == ';')) // check for "};" added V2.01
- isImmediatelyPostNonInStmt = true;
- if (!shouldBreakOneLineStatements
- && ASBeautifier::getNextWord(currentLine, charNum) == AS_ELSE)
- {
- // handle special case of "else" at the end of line
- size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
- if (ASBeautifier::peekNextChar(currentLine, nextText + 3) == ' ')
- shouldBreakLineAtNextChar = true;
- }
- }
- // format braces
- appendOpeningBrace = false;
- if (isBraceType(braceType, ARRAY_TYPE))
- {
- formatArrayBraces(braceType, isOpeningArrayBrace);
- }
- else
- {
- if (currentChar == '{')
- formatOpeningBrace(braceType);
- else
- formatClosingBrace(braceType);
- }
- continue;
- }
- if ((((previousCommandChar == '{' && isPreviousBraceBlockRelated)
- || ((previousCommandChar == '}'
- && !isImmediatelyPostEmptyBlock
- && isPreviousBraceBlockRelated
- && !isPreviousCharPostComment // Fixes wrongly appended newlines after '}' immediately after comments
- && peekNextChar() != ' '
- && !isBraceType(previousBraceType, DEFINITION_TYPE))
- && !isBraceType(braceTypeStack->back(), DEFINITION_TYPE)))
- && isOkToBreakBlock(braceTypeStack->back()))
- // check for array
- || (previousCommandChar == '{' // added 9/30/2010
- && isBraceType(braceTypeStack->back(), ARRAY_TYPE)
- && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
- && isNonInStatementArray)
- // check for pico one line braces
- || (formattingStyle == STYLE_PICO
- && (previousCommandChar == '{' && isPreviousBraceBlockRelated)
- && isBraceType(braceTypeStack->back(), COMMAND_TYPE)
- && isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
- && braceFormatMode == RUN_IN_MODE)
- )
- {
- isCharImmediatelyPostOpenBlock = (previousCommandChar == '{');
- isCharImmediatelyPostCloseBlock = (previousCommandChar == '}');
- if (isCharImmediatelyPostOpenBlock
- && !isCharImmediatelyPostComment
- && !isCharImmediatelyPostLineComment)
- {
- previousCommandChar = ' ';
- if (braceFormatMode == NONE_MODE)
- {
- if (isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
- && (isBraceType(braceTypeStack->back(), BREAK_BLOCK_TYPE)
- || shouldBreakOneLineBlocks))
- isInLineBreak = true;
- else if (currentLineBeginsWithBrace)
- formatRunIn();
- else
- breakLine();
- }
- else if (braceFormatMode == RUN_IN_MODE
- && currentChar != '#')
- formatRunIn();
- else
- isInLineBreak = true;
- }
- else if (isCharImmediatelyPostCloseBlock
- && shouldBreakOneLineStatements
- && !isCharImmediatelyPostComment
- && ((isLegalNameChar(currentChar) && currentChar != '.')
- || currentChar == '+'
- || currentChar == '-'
- || currentChar == '*'
- || currentChar == '&'
- || currentChar == '('))
- {
- previousCommandChar = ' ';
- isInLineBreak = true;
- }
- }
- // reset block handling flags
- isImmediatelyPostEmptyBlock = false;
- // look for headers
- bool isPotentialHeader = isCharPotentialHeader(currentLine, charNum);
- if (isPotentialHeader && !isInTemplate && squareBracketCount == 0)
- {
- isNonParenHeader = false;
- foundClosingHeader = false;
- newHeader = findHeader(headers);
- // Qt headers may be variables in C++
- if (isCStyle()
- && (newHeader == &AS_FOREVER || newHeader == &AS_FOREACH))
- {
- if (currentLine.find_first_of("=;", charNum) != string::npos)
- newHeader = nullptr;
- }
- if (isJavaStyle()
- && (newHeader == &AS_SYNCHRONIZED))
- {
- // want synchronized statements not synchronized methods
- if (!isBraceType(braceTypeStack->back(), COMMAND_TYPE))
- newHeader = nullptr;
- }
- else if (newHeader == &AS_USING
- && ASBeautifier::peekNextChar(
- currentLine, charNum + (*newHeader).length() - 1) != '(')
- newHeader = nullptr;
- if (newHeader != nullptr)
- {
- foundClosingHeader = isClosingHeader(newHeader);
- if (!foundClosingHeader)
- {
- // these are closing headers
- if ((newHeader == &AS_WHILE && currentHeader == &AS_DO)
- || (newHeader == &_AS_FINALLY && currentHeader == &_AS_TRY)
- || (newHeader == &_AS_EXCEPT && currentHeader == &_AS_TRY))
- foundClosingHeader = true;
- // don't append empty block for these related headers
- else if (isSharpStyle()
- && previousNonWSChar == '}'
- && ((newHeader == &AS_SET && currentHeader == &AS_GET)
- || (newHeader == &AS_REMOVE && currentHeader == &AS_ADD))
- && isOkToBreakBlock(braceTypeStack->back()))
- isAppendPostBlockEmptyLineRequested = false;
- }
- // TODO: this can be removed in a future release
- // version 3.0 - break erroneous attached header from previous versions
- if (isSharpStyle()
- && ((newHeader == &AS_SET && currentHeader == &AS_GET)
- || (newHeader == &AS_REMOVE && currentHeader == &AS_ADD))
- && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
- && currentLine[currentLine.find_first_not_of(" \t")] == '}')
- isInLineBreak = true;
- // END TODO
- const string* previousHeader = currentHeader;
- currentHeader = newHeader;
- needHeaderOpeningBrace = true;
- // is the previous statement on the same line?
- if ((previousNonWSChar == ';' || previousNonWSChar == ':')
- && !isInLineBreak
- && isOkToBreakBlock(braceTypeStack->back()))
- {
- // if breaking lines, break the line at the header
- // except for multiple 'case' statements on a line
- if (maxCodeLength != string::npos
- && previousHeader != &AS_CASE)
- isInLineBreak = true;
- else
- isHeaderInMultiStatementLine = true;
- }
- if (foundClosingHeader && previousNonWSChar == '}')
- {
- if (isOkToBreakBlock(braceTypeStack->back()))
- isLineBreakBeforeClosingHeader();
- // get the adjustment for a comment following the closing header
- if (isInLineBreak)
- nextLineSpacePadNum = getNextLineCommentAdjustment();
- else
- spacePadNum = getCurrentLineCommentAdjustment();
- }
- // check if the found header is non-paren header
- isNonParenHeader = findHeader(nonParenHeaders) != nullptr;
- if (isNonParenHeader
- && (currentHeader == &AS_CATCH
- || currentHeader == &AS_CASE))
- {
- int startChar = charNum + currentHeader->length() - 1;
- if (ASBeautifier::peekNextChar(currentLine, startChar) == '(')
- isNonParenHeader = false;
- }
- // join 'else if' statements
- if (currentHeader == &AS_IF
- && previousHeader == &AS_ELSE
- && isInLineBreak
- && !shouldBreakElseIfs
- && !isCharImmediatelyPostLineComment
- && !isImmediatelyPostPreprocessor)
- {
- // 'else' must be last thing on the line
- size_t start = formattedLine.length() >= 6 ? formattedLine.length() - 6 : 0;
- if (formattedLine.find(AS_ELSE, start) != string::npos)
- {
- appendSpacePad();
- isInLineBreak = false;
- }
- }
- appendSequence(*currentHeader);
- goForward(currentHeader->length() - 1);
- // if a paren-header is found add a space after it, if needed
- // this checks currentLine, appendSpacePad() checks formattedLine
- // in 'case' and C# 'catch' can be either a paren or non-paren header
- if (shouldPadHeader
- && !isNonParenHeader
- && charNum < (int) currentLine.length() - 1 && !isWhiteSpace(currentLine[charNum + 1]))
- appendSpacePad();
- // Signal that a header has been reached
- // *** But treat a closing while() (as in do...while)
- // as if it were NOT a header since a closing while()
- // should never have a block after it!
- if (currentHeader != &AS_CASE && currentHeader != &AS_DEFAULT
- && !(foundClosingHeader && currentHeader == &AS_WHILE))
- {
- isInHeader = true;
- // in C# 'catch' and 'delegate' can be a paren or non-paren header
- if (isNonParenHeader && !isSharpStyleWithParen(currentHeader))
- {
- isImmediatelyPostHeader = true;
- isInHeader = false;
- }
- }
- if (shouldBreakBlocks
- && isOkToBreakBlock(braceTypeStack->back())
- && !isHeaderInMultiStatementLine)
- {
- if (previousHeader == nullptr
- && !foundClosingHeader
- && !isCharImmediatelyPostOpenBlock
- && !isImmediatelyPostCommentOnly)
- {
- isPrependPostBlockEmptyLineRequested = true;
- }
- if (isClosingHeader(currentHeader)
- || foundClosingHeader)
- {
- isPrependPostBlockEmptyLineRequested = false;
- }
- if (shouldBreakClosingHeaderBlocks
- && isCharImmediatelyPostCloseBlock
- && !isImmediatelyPostCommentOnly
- && !(currentHeader == &AS_WHILE // do-while
- && foundClosingHeader))
- {
- isPrependPostBlockEmptyLineRequested = true;
- }
- }
- if (currentHeader == &AS_CASE
- || currentHeader == &AS_DEFAULT)
- isInCase = true;
- continue;
- }
- else if ((newHeader = findHeader(preDefinitionHeaders)) != nullptr
- && parenStack->back() == 0
- && !isInEnum) // not C++11 enum class
- {
- if (newHeader == &AS_NAMESPACE || newHeader == &AS_MODULE)
- foundNamespaceHeader = true;
- if (newHeader == &AS_CLASS)
- foundClassHeader = true;
- if (newHeader == &AS_STRUCT)
- foundStructHeader = true;
- if (newHeader == &AS_INTERFACE)
- foundInterfaceHeader = true;
- foundPreDefinitionHeader = true;
- appendSequence(*newHeader);
- goForward(newHeader->length() - 1);
- continue;
- }
- else if ((newHeader = findHeader(preCommandHeaders)) != nullptr)
- {
- // a 'const' variable is not a preCommandHeader
- if (previousNonWSChar == ')')
- foundPreCommandHeader = true;
- }
- else if ((newHeader = findHeader(castOperators)) != nullptr)
- {
- foundCastOperator = true;
- appendSequence(*newHeader);
- goForward(newHeader->length() - 1);
- continue;
- }
- } // (isPotentialHeader && !isInTemplate)
- if (isInLineBreak) // OK to break line here
- {
- breakLine();
- if (isInVirginLine) // adjust for the first line
- {
- lineCommentNoBeautify = lineCommentNoIndent;
- lineCommentNoIndent = false;
- if (isImmediatelyPostPreprocessor)
- {
- isInIndentablePreproc = isIndentableProprocessor;
- isIndentableProprocessor = false;
- }
- }
- }
- if (previousNonWSChar == '}' || currentChar == ';')
- {
- if (currentChar == ';')
- {
- squareBracketCount = 0;
- if (((shouldBreakOneLineStatements
- || isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE))
- && isOkToBreakBlock(braceTypeStack->back()))
- && !(attachClosingBraceMode && peekNextChar() == '}'))
- {
- passedSemicolon = true;
- }
- else if (!shouldBreakOneLineStatements
- && ASBeautifier::getNextWord(currentLine, charNum) == AS_ELSE)
- {
- // handle special case of "else" at the end of line
- size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
- if (ASBeautifier::peekNextChar(currentLine, nextText + 3) == ' ')
- passedSemicolon = true;
- }
- if (shouldBreakBlocks
- && currentHeader != nullptr
- && currentHeader != &AS_CASE
- && currentHeader != &AS_DEFAULT
- && !isHeaderInMultiStatementLine
- && parenStack->back() == 0)
- {
- isAppendPostBlockEmptyLineRequested = true;
- }
- }
- if (currentChar != ';'
- || (needHeaderOpeningBrace && parenStack->back() == 0))
- currentHeader = nullptr;
- resetEndOfStatement();
- }
- if (currentChar == ':'
- && previousChar != ':' // not part of '::'
- && peekNextChar() != ':') // not part of '::'
- {
- if (isInCase)
- {
- isInCase = false;
- if (shouldBreakOneLineStatements)
- passedColon = true;
- }
- else if (isCStyle() // for C/C++ only
- && isOkToBreakBlock(braceTypeStack->back())
- && shouldBreakOneLineStatements
- && !foundQuestionMark // not in a ?: sequence
- && !foundPreDefinitionHeader // not in a definition block
- && previousCommandChar != ')' // not after closing paren of a method header
- && !foundPreCommandHeader // not after a 'noexcept'
- && squareBracketCount == 0 // not in objC method call
- && !isInObjCMethodDefinition // not objC '-' or '+' method
- && !isInObjCInterface // not objC @interface
- && !isInObjCSelector // not objC @selector
- && !isDigit(peekNextChar()) // not a bit field
- && !isInEnum // not an enum with a base type
- && !isInAsm // not in extended assembler
- && !isInAsmOneLine // not in extended assembler
- && !isInAsmBlock) // not in extended assembler
- {
- passedColon = true;
- }
- if (isCStyle()
- && shouldPadMethodColon
- && (squareBracketCount > 0 || isInObjCMethodDefinition || isInObjCSelector)
- && !foundQuestionMark) // not in a ?: sequence
- padObjCMethodColon();
- if (isInObjCInterface)
- {
- appendSpacePad();
- if ((int) currentLine.length() > charNum + 1
- && !isWhiteSpace(currentLine[charNum + 1]))
- currentLine.insert(charNum + 1, " ");
- }
- if (isClassInitializer())
- isInClassInitializer = true;
- }
- if (currentChar == '?')
- foundQuestionMark = true;
- if (isPotentialHeader && !isInTemplate)
- {
- if (findKeyword(currentLine, charNum, AS_NEW)
- || findKeyword(currentLine, charNum, AS_DELETE))
- {
- isInPotentialCalculation = false;
- isImmediatelyPostNewDelete = true;
- }
- if (findKeyword(currentLine, charNum, AS_RETURN))
- {
- isInPotentialCalculation = true; // return is the same as an = sign
- isImmediatelyPostReturn = true;
- }
- if (findKeyword(currentLine, charNum, AS_OPERATOR))
- isImmediatelyPostOperator = true;
- if (findKeyword(currentLine, charNum, AS_ENUM))
- {
- size_t firstNum = currentLine.find_first_of("(){},/");
- if (firstNum == string::npos
- || currentLine[firstNum] == '{'
- || currentLine[firstNum] == '/')
- isInEnum = true;
- }
- if (isCStyle()
- && findKeyword(currentLine, charNum, AS_THROW)
- && previousCommandChar != ')'
- && !foundPreCommandHeader) // 'const' throw()
- isImmediatelyPostThrow = true;
- if (isCStyle() && findKeyword(currentLine, charNum, AS_EXTERN) && isExternC())
- isInExternC = true;
- if (isCStyle() && findKeyword(currentLine, charNum, AS_AUTO)
- && (isBraceType(braceTypeStack->back(), NULL_TYPE)
- || isBraceType(braceTypeStack->back(), NAMESPACE_TYPE)
- || isBraceType(braceTypeStack->back(), CLASS_TYPE)))
- foundTrailingReturnType = true;
- // Objective-C NSException macros are preCommandHeaders
- if (isCStyle() && findKeyword(currentLine, charNum, AS_NS_DURING))
- foundPreCommandMacro = true;
- if (isCStyle() && findKeyword(currentLine, charNum, AS_NS_HANDLER))
- foundPreCommandMacro = true;
- if (isCStyle() && isExecSQL(currentLine, charNum))
- isInExecSQL = true;
- if (isCStyle())
- {
- if (findKeyword(currentLine, charNum, AS_ASM)
- || findKeyword(currentLine, charNum, AS__ASM__))
- {
- isInAsm = true;
- }
- else if (findKeyword(currentLine, charNum, AS_MS_ASM) // microsoft specific
- || findKeyword(currentLine, charNum, AS_MS__ASM))
- {
- int index = 4;
- if (peekNextChar() == '_') // check for __asm
- index = 5;
- char peekedChar = ASBase::peekNextChar(currentLine, charNum + index);
- if (peekedChar == '{' || peekedChar == ' ')
- isInAsmBlock = true;
- else
- isInAsmOneLine = true;
- }
- }
- if (isJavaStyle()
- && (findKeyword(currentLine, charNum, AS_STATIC)
- && isNextCharOpeningBrace(charNum + 6)))
- isJavaStaticConstructor = true;
- if (isSharpStyle()
- && (findKeyword(currentLine, charNum, AS_DELEGATE)
- || findKeyword(currentLine, charNum, AS_UNCHECKED)))
- isSharpDelegate = true;
- // append the entire name
- string name = getCurrentWord(currentLine, charNum);
- // must pad the 'and' and 'or' operators if required
- if (name == "and" || name == "or")
- {
- if (shouldPadOperators && previousNonWSChar != ':')
- {
- appendSpacePad();
- appendOperator(name);
- goForward(name.length() - 1);
- if (!isBeforeAnyComment()
- && !(currentLine.compare(charNum + 1, 1, AS_SEMICOLON) == 0)
- && !(currentLine.compare(charNum + 1, 2, AS_SCOPE_RESOLUTION) == 0))
- appendSpaceAfter();
- }
- else
- {
- appendOperator(name);
- goForward(name.length() - 1);
- }
- }
- else
- {
- appendSequence(name);
- goForward(name.length() - 1);
- }
- continue;
- } // (isPotentialHeader && !isInTemplate)
- // determine if this is an Objective-C statement
- if (currentChar == '@'
- && isCharPotentialHeader(currentLine, charNum + 1)
- && findKeyword(currentLine, charNum + 1, AS_INTERFACE)
- && isBraceType(braceTypeStack->back(), NULL_TYPE))
- {
- isInObjCInterface = true;
- string name = '@' + AS_INTERFACE;
- appendSequence(name);
- goForward(name.length() - 1);
- continue;
- }
- else if (currentChar == '@'
- && isCharPotentialHeader(currentLine, charNum + 1)
- && findKeyword(currentLine, charNum + 1, AS_SELECTOR))
- {
- isInObjCSelector = true;
- string name = '@' + AS_SELECTOR;
- appendSequence(name);
- goForward(name.length() - 1);
- continue;
- }
- else if ((currentChar == '-' || currentChar == '+')
- && (int) currentLine.find_first_not_of(" \t") == charNum
- && peekNextChar() == '('
- && isBraceType(braceTypeStack->back(), NULL_TYPE)
- && !isInPotentialCalculation)
- {
- isInObjCMethodDefinition = true;
- isImmediatelyPostObjCMethodPrefix = true;
- isInObjCInterface = false;
- if (getAlignMethodColon())
- objCColonAlign = findObjCColonAlignment();
- appendCurrentChar();
- continue;
- }
- // determine if this is a potential calculation
- bool isPotentialOperator = isCharPotentialOperator(currentChar);
- newHeader = nullptr;
- if (isPotentialOperator)
- {
- newHeader = findOperator(operators);
- // check for Java ? wildcard
- if (newHeader != nullptr
- && newHeader == &AS_GCC_MIN_ASSIGN
- && isJavaStyle()
- && isInTemplate)
- newHeader = nullptr;
- if (newHeader != nullptr)
- {
- if (newHeader == &AS_LAMBDA)
- foundPreCommandHeader = true;
- // correct mistake of two >> closing a template
- if (isInTemplate && (newHeader == &AS_GR_GR || newHeader == &AS_GR_GR_GR))
- newHeader = &AS_GR;
- if (!isInPotentialCalculation)
- {
- // must determine if newHeader is an assignment operator
- // do NOT use findOperator - the length must be exact!!!
- if (find(begin(*assignmentOperators), end(*assignmentOperators), newHeader)
- != end(*assignmentOperators))
- {
- foundPreCommandHeader = false;
- char peekedChar = peekNextChar();
- isInPotentialCalculation = !(newHeader == &AS_EQUAL && peekedChar == '*')
- && !(newHeader == &AS_EQUAL && peekedChar == '&')
- && !isCharImmediatelyPostOperator;
- }
- }
- }
- }
- // process pointers and references
- // check newHeader to eliminate things like '&&' sequence
- if (newHeader != nullptr && !isJavaStyle()
- && (newHeader == &AS_MULT
- || newHeader == &AS_BIT_AND
- || newHeader == &AS_BIT_XOR
- || newHeader == &AS_AND)
- && isPointerOrReference())
- {
- if (!isDereferenceOrAddressOf() && !isOperatorPaddingDisabled())
- formatPointerOrReference();
- else
- {
- appendOperator(*newHeader);
- goForward(newHeader->length() - 1);
- }
- isImmediatelyPostPointerOrReference = true;
- continue;
- }
- if (shouldPadOperators && newHeader != nullptr && !isOperatorPaddingDisabled())
- {
- padOperators(newHeader);
- continue;
- }
- // remove spaces before commas
- if (currentChar == ',')
- {
- const size_t len = formattedLine.length();
- size_t lastText = formattedLine.find_last_not_of(' ');
- if (lastText != string::npos && lastText < len - 1)
- {
- formattedLine.resize(lastText + 1);
- int size_diff = len - (lastText + 1);
- spacePadNum -= size_diff;
- }
- }
- // pad commas and semi-colons
- if (currentChar == ';'
- || (currentChar == ',' && (shouldPadOperators || shouldPadCommas)))
- {
- char nextChar = ' ';
- if (charNum + 1 < (int) currentLine.length())
- nextChar = currentLine[charNum + 1];
- if (!isWhiteSpace(nextChar)
- && nextChar != '}'
- && nextChar != ')'
- && nextChar != ']'
- && nextChar != '>'
- && nextChar != ';'
- && !isBeforeAnyComment()
- /* && !(isBraceType(braceTypeStack->back(), ARRAY_TYPE)) */
- )
- {
- appendCurrentChar();
- appendSpaceAfter();
- continue;
- }
- }
- // pad parens
- if (currentChar == '(' || currentChar == ')')
- {
- if (currentChar == '(')
- {
- if (shouldPadHeader
- && (isCharImmediatelyPostReturn
- || isCharImmediatelyPostThrow
- || isCharImmediatelyPostNewDelete))
- appendSpacePad();
- }
- if (shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens || shouldPadFirstParen)
- padParens();
- else
- appendCurrentChar();
- if (isInObjCMethodDefinition)
- {
- if (currentChar == '(' && isImmediatelyPostObjCMethodPrefix)
- {
- if (shouldPadMethodPrefix || shouldUnPadMethodPrefix)
- padObjCMethodPrefix();
- isImmediatelyPostObjCMethodPrefix = false;
- isInObjCReturnType = true;
- }
- else if (currentChar == ')' && isInObjCReturnType)
- {
- if (shouldPadReturnType || shouldUnPadReturnType)
- padObjCReturnType();
- isInObjCReturnType = false;
- }
- else if (shouldPadParamType || shouldUnPadParamType)
- padObjCParamType();
- }
- continue;
- }
- // bypass the entire operator
- if (newHeader != nullptr)
- {
- appendOperator(*newHeader);
- goForward(newHeader->length() - 1);
- continue;
- }
- appendCurrentChar();
- } // end of while loop * end of while loop * end of while loop * end of while loop
- // return a beautified (i.e. correctly indented) line.
- string beautifiedLine;
- size_t readyFormattedLineLength = trim(readyFormattedLine).length();
- bool isInNamespace = isBraceType(braceTypeStack->back(), NAMESPACE_TYPE);
- if (prependEmptyLine // prepend a blank line before this formatted line
- && readyFormattedLineLength > 0
- && previousReadyFormattedLineLength > 0)
- {
- isLineReady = true; // signal a waiting readyFormattedLine
- beautifiedLine = beautify("");
- previousReadyFormattedLineLength = 0;
- // call the enhancer for new empty lines
- enhancer->enhance(beautifiedLine, isInNamespace, isInPreprocessorBeautify, isInBeautifySQL);
- }
- else // format the current formatted line
- {
- isLineReady = false;
- runInIndentContinuation = runInIndentChars;
- beautifiedLine = beautify(readyFormattedLine);
- previousReadyFormattedLineLength = readyFormattedLineLength;
- // the enhancer is not called for no-indent line comments
- if (!lineCommentNoBeautify && !isFormattingModeOff)
- enhancer->enhance(beautifiedLine, isInNamespace, isInPreprocessorBeautify, isInBeautifySQL);
- runInIndentChars = 0;
- lineCommentNoBeautify = lineCommentNoIndent;
- lineCommentNoIndent = false;
- isInIndentablePreproc = isIndentableProprocessor;
- isIndentableProprocessor = false;
- isElseHeaderIndent = elseHeaderFollowsComments;
- isCaseHeaderCommentIndent = caseHeaderFollowsComments;
- objCColonAlignSubsequent = objCColonAlign;
- if (isCharImmediatelyPostNonInStmt)
- {
- isNonInStatementArray = false;
- isCharImmediatelyPostNonInStmt = false;
- }
- isInPreprocessorBeautify = isInPreprocessor; // used by ASEnhancer
- isInBeautifySQL = isInExecSQL; // used by ASEnhancer
- }
- prependEmptyLine = false;
- assert(computeChecksumOut(beautifiedLine));
- return beautifiedLine;
- }
- /**
- * check if there are any indented lines ready to be read by nextLine()
- *
- * @return are there any indented lines ready?
- */
- bool ASFormatter::hasMoreLines() const
- {
- return !endOfCodeReached;
- }
- /**
- * comparison function for BraceType enum
- */
- bool ASFormatter::isBraceType(BraceType a, BraceType b) const
- {
- if (a == NULL_TYPE || b == NULL_TYPE)
- return (a == b);
- return ((a & b) == b);
- }
- /**
- * set the formatting style.
- *
- * @param style the formatting style.
- */
- void ASFormatter::setFormattingStyle(FormatStyle style)
- {
- formattingStyle = style;
- }
- /**
- * set the add braces mode.
- * options:
- * true braces added to headers for single line statements.
- * false braces NOT added to headers for single line statements.
- *
- * @param state the add braces state.
- */
- void ASFormatter::setAddBracesMode(bool state)
- {
- shouldAddBraces = state;
- }
- /**
- * set the add one line braces mode.
- * options:
- * true one line braces added to headers for single line statements.
- * false one line braces NOT added to headers for single line statements.
- *
- * @param state the add one line braces state.
- */
- void ASFormatter::setAddOneLineBracesMode(bool state)
- {
- shouldAddBraces = state;
- shouldAddOneLineBraces = state;
- }
- /**
- * set the remove braces mode.
- * options:
- * true braces removed from headers for single line statements.
- * false braces NOT removed from headers for single line statements.
- *
- * @param state the remove braces state.
- */
- void ASFormatter::setRemoveBracesMode(bool state)
- {
- shouldRemoveBraces = state;
- }
- // retained for compatability with release 2.06
- // "Brackets" have been changed to "Braces" in 3.0
- // it is referenced only by the old "bracket" options
- void ASFormatter::setAddBracketsMode(bool state)
- {
- setAddBracesMode(state);
- }
- // retained for compatability with release 2.06
- // "Brackets" have been changed to "Braces" in 3.0
- // it is referenced only by the old "bracket" options
- void ASFormatter::setAddOneLineBracketsMode(bool state)
- {
- setAddOneLineBracesMode(state);
- }
- // retained for compatability with release 2.06
- // "Brackets" have been changed to "Braces" in 3.0
- // it is referenced only by the old "bracket" options
- void ASFormatter::setRemoveBracketsMode(bool state)
- {
- setRemoveBracesMode(state);
- }
- // retained for compatability with release 2.06
- // "Brackets" have been changed to "Braces" in 3.0
- // it is referenced only by the old "bracket" options
- void ASFormatter::setBreakClosingHeaderBracketsMode(bool state)
- {
- setBreakClosingHeaderBracesMode(state);
- }
- /**
- * set the brace formatting mode.
- * options:
- *
- * @param mode the brace formatting mode.
- */
- void ASFormatter::setBraceFormatMode(BraceMode mode)
- {
- braceFormatMode = mode;
- }
- /**
- * set 'break after' mode for maximum code length
- *
- * @param state the 'break after' mode.
- */
- void ASFormatter::setBreakAfterMode(bool state)
- {
- shouldBreakLineAfterLogical = state;
- }
- /**
- * set closing header brace breaking mode
- * options:
- * true braces just before closing headers (e.g. 'else', 'catch')
- * will be broken, even if standard braces are attached.
- * false closing header braces will be treated as standard braces.
- *
- * @param state the closing header brace breaking mode.
- */
- void ASFormatter::setBreakClosingHeaderBracesMode(bool state)
- {
- shouldBreakClosingHeaderBraces = state;
- }
- /**
- * set 'else if()' breaking mode
- * options:
- * true 'else' headers will be broken from their succeeding 'if' headers.
- * false 'else' headers will be attached to their succeeding 'if' headers.
- *
- * @param state the 'else if()' breaking mode.
- */
- void ASFormatter::setBreakElseIfsMode(bool state)
- {
- shouldBreakElseIfs = state;
- }
- /**
- * set comma padding mode.
- * options:
- * true statement commas and semicolons will be padded with spaces around them.
- * false statement commas and semicolons will not be padded.
- *
- * @param state the padding mode.
- */
- void ASFormatter::setCommaPaddingMode(bool state)
- {
- shouldPadCommas = state;
- }
- /**
- * set maximum code length
- *
- * @param max the maximum code length.
- */
- void ASFormatter::setMaxCodeLength(int max)
- {
- maxCodeLength = max;
- }
- /**
- * set operator padding mode.
- * options:
- * true statement operators will be padded with spaces around them.
- * false statement operators will not be padded.
- *
- * @param state the padding mode.
- */
- void ASFormatter::setOperatorPaddingMode(bool state)
- {
- shouldPadOperators = state;
- }
- /**
- * set parenthesis outside padding mode.
- * options:
- * true statement parentheses will be padded with spaces around them.
- * false statement parentheses will not be padded.
- *
- * @param state the padding mode.
- */
- void ASFormatter::setParensOutsidePaddingMode(bool state)
- {
- shouldPadParensOutside = state;
- }
- /**
- * set parenthesis inside padding mode.
- * options:
- * true statement parenthesis will be padded with spaces around them.
- * false statement parenthesis will not be padded.
- *
- * @param state the padding mode.
- */
- void ASFormatter::setParensInsidePaddingMode(bool state)
- {
- shouldPadParensInside = state;
- }
- /**
- * set padding mode before one or more open parentheses.
- * options:
- * true first open parenthesis will be padded with a space before.
- * false first open parenthesis will not be padded.
- *
- * @param state the padding mode.
- */
- void ASFormatter::setParensFirstPaddingMode(bool state)
- {
- shouldPadFirstParen = state;
- }
- /**
- * set header padding mode.
- * options:
- * true headers will be padded with spaces around them.
- * false headers will not be padded.
- *
- * @param state the padding mode.
- */
- void ASFormatter::setParensHeaderPaddingMode(bool state)
- {
- shouldPadHeader = state;
- }
- /**
- * set parenthesis unpadding mode.
- * options:
- * true statement parenthesis will be unpadded with spaces removed around them.
- * false statement parenthesis will not be unpadded.
- *
- * @param state the padding mode.
- */
- void ASFormatter::setParensUnPaddingMode(bool state)
- {
- shouldUnPadParens = state;
- }
- /**
- * set the state of the preprocessor indentation option.
- * If true, #ifdef blocks at level 0 will be indented.
- *
- * @param state state of option.
- */
- void ASFormatter::setPreprocBlockIndent(bool state)
- {
- shouldIndentPreprocBlock = state;
- }
- /**
- * Set strip comment prefix mode.
- * options:
- * true strip leading '*' in a comment.
- * false leading '*' in a comment will be left unchanged.
- *
- * @param state the strip comment prefix mode.
- */
- void ASFormatter::setStripCommentPrefix(bool state)
- {
- shouldStripCommentPrefix = state;
- }
- /**
- * set objective-c '-' or '+' class prefix padding mode.
- * options:
- * true class prefix will be padded a spaces after them.
- * false class prefix will be left unchanged.
- *
- * @param state the padding mode.
- */
- void ASFormatter::setMethodPrefixPaddingMode(bool state)
- {
- shouldPadMethodPrefix = state;
- }
- /**
- * set objective-c '-' or '+' class prefix unpadding mode.
- * options:
- * true class prefix will be unpadded with spaces after them removed.
- * false class prefix will left unchanged.
- *
- * @param state the unpadding mode.
- */
- void ASFormatter::setMethodPrefixUnPaddingMode(bool state)
- {
- shouldUnPadMethodPrefix = state;
- }
- // set objective-c '-' or '+' return type padding mode.
- void ASFormatter::setReturnTypePaddingMode(bool state)
- {
- shouldPadReturnType = state;
- }
- // set objective-c '-' or '+' return type unpadding mode.
- void ASFormatter::setReturnTypeUnPaddingMode(bool state)
- {
- shouldUnPadReturnType = state;
- }
- // set objective-c method parameter type padding mode.
- void ASFormatter::setParamTypePaddingMode(bool state)
- {
- shouldPadParamType = state;
- }
- // set objective-c method parameter type unpadding mode.
- void ASFormatter::setParamTypeUnPaddingMode(bool state)
- {
- shouldUnPadParamType = state;
- }
- /**
- * set objective-c method colon padding mode.
- *
- * @param mode objective-c colon padding mode.
- */
- void ASFormatter::setObjCColonPaddingMode(ObjCColonPad mode)
- {
- shouldPadMethodColon = true;
- objCColonPadMode = mode;
- }
- /**
- * set option to attach closing braces
- *
- * @param state true = attach, false = don't attach.
- */
- void ASFormatter::setAttachClosingBraceMode(bool state)
- {
- attachClosingBraceMode = state;
- }
- /**
- * set option to attach class braces
- *
- * @param state true = attach, false = use style default.
- */
- void ASFormatter::setAttachClass(bool state)
- {
- shouldAttachClass = state;
- }
- /**
- * set option to attach extern "C" braces
- *
- * @param state true = attach, false = use style default.
- */
- void ASFormatter::setAttachExternC(bool state)
- {
- shouldAttachExternC = state;
- }
- /**
- * set option to attach namespace braces
- *
- * @param state true = attach, false = use style default.
- */
- void ASFormatter::setAttachNamespace(bool state)
- {
- shouldAttachNamespace = state;
- }
- /**
- * set option to attach inline braces
- *
- * @param state true = attach, false = use style default.
- */
- void ASFormatter::setAttachInline(bool state)
- {
- shouldAttachInline = state;
- }
- void ASFormatter::setAttachClosingWhile(bool state)
- {
- shouldAttachClosingWhile = state;
- }
- /**
- * set option to break/not break one-line blocks
- *
- * @param state true = break, false = don't break.
- */
- void ASFormatter::setBreakOneLineBlocksMode(bool state)
- {
- shouldBreakOneLineBlocks = state;
- }
- /**
- * set one line headers breaking mode
- */
- void ASFormatter::setBreakOneLineHeadersMode(bool state)
- {
- shouldBreakOneLineHeaders = state;
- }
- /**
- * set option to break/not break lines consisting of multiple statements.
- *
- * @param state true = break, false = don't break.
- */
- void ASFormatter::setBreakOneLineStatementsMode(bool state)
- {
- shouldBreakOneLineStatements = state;
- }
- void ASFormatter::setCloseTemplatesMode(bool state)
- {
- shouldCloseTemplates = state;
- }
- /**
- * set option to convert tabs to spaces.
- *
- * @param state true = convert, false = don't convert.
- */
- void ASFormatter::setTabSpaceConversionMode(bool state)
- {
- shouldConvertTabs = state;
- }
- /**
- * set option to indent comments in column 1.
- *
- * @param state true = indent, false = don't indent.
- */
- void ASFormatter::setIndentCol1CommentsMode(bool state)
- {
- shouldIndentCol1Comments = state;
- }
- /**
- * set option to force all line ends to a particular style.
- *
- * @param fmt format enum value
- */
- void ASFormatter::setLineEndFormat(LineEndFormat fmt)
- {
- lineEnd = fmt;
- }
- /**
- * set option to break unrelated blocks of code with empty lines.
- *
- * @param state true = convert, false = don't convert.
- */
- void ASFormatter::setBreakBlocksMode(bool state)
- {
- shouldBreakBlocks = state;
- }
- /**
- * set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines.
- *
- * @param state true = convert, false = don't convert.
- */
- void ASFormatter::setBreakClosingHeaderBlocksMode(bool state)
- {
- shouldBreakClosingHeaderBlocks = state;
- }
- /**
- * set option to delete empty lines.
- *
- * @param state true = delete, false = don't delete.
- */
- void ASFormatter::setDeleteEmptyLinesMode(bool state)
- {
- shouldDeleteEmptyLines = state;
- }
- /**
- * set the pointer alignment.
- *
- * @param alignment the pointer alignment.
- */
- void ASFormatter::setPointerAlignment(PointerAlign alignment)
- {
- pointerAlignment = alignment;
- }
- void ASFormatter::setReferenceAlignment(ReferenceAlign alignment)
- {
- referenceAlignment = alignment;
- }
- /**
- * jump over several characters.
- *
- * @param i the number of characters to jump over.
- */
- void ASFormatter::goForward(int i)
- {
- while (--i >= 0)
- getNextChar();
- }
- /**
- * peek at the next unread character.
- *
- * @return the next unread character.
- */
- char ASFormatter::peekNextChar() const
- {
- char ch = ' ';
- size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
- if (peekNum == string::npos)
- return ch;
- ch = currentLine[peekNum];
- return ch;
- }
- /**
- * check if current placement is before a comment
- *
- * @return is before a comment.
- */
- bool ASFormatter::isBeforeComment() const
- {
- bool foundComment = false;
- size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
- if (peekNum == string::npos)
- return foundComment;
- foundComment = (currentLine.compare(peekNum, 2, "/*") == 0);
- return foundComment;
- }
- /**
- * check if current placement is before a comment or line-comment
- *
- * @return is before a comment or line-comment.
- */
- bool ASFormatter::isBeforeAnyComment() const
- {
- bool foundComment = false;
- size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
- if (peekNum == string::npos)
- return foundComment;
- foundComment = (currentLine.compare(peekNum, 2, "/*") == 0
- || currentLine.compare(peekNum, 2, "//") == 0);
- return foundComment;
- }
- /**
- * check if current placement is before a comment or line-comment
- * if a block comment it must be at the end of the line
- *
- * @return is before a comment or line-comment.
- */
- bool ASFormatter::isBeforeAnyLineEndComment(int startPos) const
- {
- bool foundLineEndComment = false;
- size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1);
- if (peekNum != string::npos)
- {
- if (currentLine.compare(peekNum, 2, "//") == 0)
- foundLineEndComment = true;
- else if (currentLine.compare(peekNum, 2, "/*") == 0)
- {
- // comment must be closed on this line with nothing after it
- size_t endNum = currentLine.find("*/", peekNum + 2);
- if (endNum != string::npos)
- {
- size_t nextChar = currentLine.find_first_not_of(" \t", endNum + 2);
- if (nextChar == string::npos)
- foundLineEndComment = true;
- }
- }
- }
- return foundLineEndComment;
- }
- /**
- * check if current placement is before a comment followed by a line-comment
- *
- * @return is before a multiple line-end comment.
- */
- bool ASFormatter::isBeforeMultipleLineEndComments(int startPos) const
- {
- bool foundMultipleLineEndComment = false;
- size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1);
- if (peekNum != string::npos)
- {
- if (currentLine.compare(peekNum, 2, "/*") == 0)
- {
- // comment must be closed on this line with nothing after it
- size_t endNum = currentLine.find("*/", peekNum + 2);
- if (endNum != string::npos)
- {
- size_t nextChar = currentLine.find_first_not_of(" \t", endNum + 2);
- if (nextChar != string::npos
- && currentLine.compare(nextChar, 2, "//") == 0)
- foundMultipleLineEndComment = true;
- }
- }
- }
- return foundMultipleLineEndComment;
- }
- /**
- * get the next character, increasing the current placement in the process.
- * the new character is inserted into the variable currentChar.
- *
- * @return whether succeeded to receive the new character.
- */
- bool ASFormatter::getNextChar()
- {
- isInLineBreak = false;
- previousChar = currentChar;
- if (!isWhiteSpace(currentChar))
- {
- previousNonWSChar = currentChar;
- if (!isInComment && !isInLineComment && !isInQuote
- && !isImmediatelyPostComment
- && !isImmediatelyPostLineComment
- && !isInPreprocessor
- && !isSequenceReached("/*")
- && !isSequenceReached("//"))
- previousCommandChar = currentChar;
- }
- if (charNum + 1 < (int) currentLine.length()
- && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment))
- {
- currentChar = currentLine[++charNum];
- if (currentChar == '\t' && shouldConvertTabs)
- convertTabToSpaces();
- return true;
- }
- // end of line has been reached
- return getNextLine();
- }
- /**
- * get the next line of input, increasing the current placement in the process.
- *
- * @param emptyLineWasDeleted an empty line was deleted.
- * @return whether succeeded in reading the next line.
- */
- bool ASFormatter::getNextLine(bool emptyLineWasDeleted /*false*/)
- {
- if (!sourceIterator->hasMoreLines())
- {
- endOfCodeReached = true;
- return false;
- }
- if (appendOpeningBrace)
- currentLine = "{"; // append brace that was removed from the previous line
- else
- {
- currentLine = sourceIterator->nextLine(emptyLineWasDeleted);
- assert(computeChecksumIn(currentLine));
- }
- // reset variables for new line
- inLineNumber++;
- if (endOfAsmReached)
- endOfAsmReached = isInAsmBlock = isInAsm = false;
- shouldKeepLineUnbroken = false;
- isInCommentStartLine = false;
- isInCase = false;
- isInAsmOneLine = false;
- isHeaderInMultiStatementLine = false;
- isInQuoteContinuation = isInVerbatimQuote || haveLineContinuationChar;
- haveLineContinuationChar = false;
- isImmediatelyPostEmptyLine = lineIsEmpty;
- previousChar = ' ';
- if (currentLine.length() == 0)
- currentLine = string(" "); // a null is inserted if this is not done
- // unless reading in the first line of the file, break a new line.
- if (!isVirgin)
- isInLineBreak = true;
- else
- isVirgin = false;
- if (isImmediatelyPostNonInStmt)
- {
- isCharImmediatelyPostNonInStmt = true;
- isImmediatelyPostNonInStmt = false;
- }
- // check if is in preprocessor before line trimming
- // a blank line after a \ will remove the flag
- isImmediatelyPostPreprocessor = isInPreprocessor;
- if (!isInComment
- && (previousNonWSChar != '\\'
- || isEmptyLine(currentLine)))
- isInPreprocessor = false;
- if (passedSemicolon)
- isInExecSQL = false;
- initNewLine();
- currentChar = currentLine[charNum];
- if (isInBraceRunIn && previousNonWSChar == '{' && !isInComment)
- isInLineBreak = false;
- isInBraceRunIn = false;
- if (currentChar == '\t' && shouldConvertTabs)
- convertTabToSpaces();
- // check for an empty line inside a command brace.
- // if yes then read the next line (calls getNextLine recursively).
- // must be after initNewLine.
- if (shouldDeleteEmptyLines
- && lineIsEmpty
- && isBraceType((*braceTypeStack)[braceTypeStack->size() - 1], COMMAND_TYPE))
- {
- if (!shouldBreakBlocks || previousNonWSChar == '{' || !commentAndHeaderFollows())
- {
- isInPreprocessor = isImmediatelyPostPreprocessor; // restore
- lineIsEmpty = false;
- return getNextLine(true);
- }
- }
- return true;
- }
- /**
- * jump over the leading white space in the current line,
- * IF the line does not begin a comment or is in a preprocessor definition.
- */
- void ASFormatter::initNewLine()
- {
- size_t len = currentLine.length();
- size_t tabSize = getTabLength();
- charNum = 0;
- // don't trim these
- if (isInQuoteContinuation
- || (isInPreprocessor && !getPreprocDefineIndent()))
- return;
- // SQL continuation lines must be adjusted so the leading spaces
- // is equivalent to the opening EXEC SQL
- if (isInExecSQL)
- {
- // replace leading tabs with spaces
- // so that continuation indent will be spaces
- size_t tabCount_ = 0;
- size_t i;
- for (i = 0; i < currentLine.length(); i++)
- {
- if (!isWhiteSpace(currentLine[i])) // stop at first text
- break;
- if (currentLine[i] == '\t')
- {
- size_t numSpaces = tabSize - ((tabCount_ + i) % tabSize);
- currentLine.replace(i, 1, numSpaces, ' ');
- tabCount_++;
- i += tabSize - 1;
- }
- }
- // this will correct the format if EXEC SQL is not a hanging indent
- trimContinuationLine();
- return;
- }
- // comment continuation lines must be adjusted so the leading spaces
- // is equivalent to the opening comment
- if (isInComment)
- {
- if (noTrimCommentContinuation)
- leadingSpaces = tabIncrementIn = 0;
- trimContinuationLine();
- return;
- }
- // compute leading spaces
- isImmediatelyPostCommentOnly = lineIsLineCommentOnly || lineEndsInCommentOnly;
- lineIsCommentOnly = false;
- lineIsLineCommentOnly = false;
- lineEndsInCommentOnly = false;
- doesLineStartComment = false;
- currentLineBeginsWithBrace = false;
- lineIsEmpty = false;
- currentLineFirstBraceNum = string::npos;
- tabIncrementIn = 0;
- // bypass whitespace at the start of a line
- // preprocessor tabs are replaced later in the program
- for (charNum = 0; isWhiteSpace(currentLine[charNum]) && charNum + 1 < (int) len; charNum++)
- {
- if (currentLine[charNum] == '\t' && !isInPreprocessor)
- tabIncrementIn += tabSize - 1 - ((tabIncrementIn + charNum) % tabSize);
- }
- leadingSpaces = charNum + tabIncrementIn;
- if (isSequenceReached("/*"))
- {
- doesLineStartComment = true;
- if ((int) currentLine.length() > charNum + 2
- && currentLine.find("*/", charNum + 2) != string::npos)
- lineIsCommentOnly = true;
- }
- else if (isSequenceReached("//"))
- {
- lineIsLineCommentOnly = true;
- }
- else if (isSequenceReached("{"))
- {
- currentLineBeginsWithBrace = true;
- currentLineFirstBraceNum = charNum;
- size_t firstText = currentLine.find_first_not_of(" \t", charNum + 1);
- if (firstText != string::npos)
- {
- if (currentLine.compare(firstText, 2, "//") == 0)
- lineIsLineCommentOnly = true;
- else if (currentLine.compare(firstText, 2, "/*") == 0
- || isExecSQL(currentLine, firstText))
- {
- // get the extra adjustment
- size_t j;
- for (j = charNum + 1; j < firstText && isWhiteSpace(currentLine[j]); j++)
- {
- if (currentLine[j] == '\t')
- tabIncrementIn += tabSize - 1 - ((tabIncrementIn + j) % tabSize);
- }
- leadingSpaces = j + tabIncrementIn;
- if (currentLine.compare(firstText, 2, "/*") == 0)
- doesLineStartComment = true;
- }
- }
- }
- else if (isWhiteSpace(currentLine[charNum]) && !(charNum + 1 < (int) currentLine.length()))
- {
- lineIsEmpty = true;
- }
- // do not trim indented preprocessor define (except for comment continuation lines)
- if (isInPreprocessor)
- {
- if (!doesLineStartComment)
- leadingSpaces = 0;
- charNum = 0;
- }
- }
- /**
- * Append a character to the current formatted line.
- * The formattedLine split points are updated.
- *
- * @param ch the character to append.
- * @param canBreakLine if true, a registered line-break
- */
- void ASFormatter::appendChar(char ch, bool canBreakLine)
- {
- if (canBreakLine && isInLineBreak)
- breakLine();
- formattedLine.append(1, ch);
- isImmediatelyPostCommentOnly = false;
- if (maxCodeLength != string::npos)
- {
- // These compares reduce the frequency of function calls.
- if (isOkToSplitFormattedLine())
- updateFormattedLineSplitPoints(ch);
- if (formattedLine.length() > maxCodeLength)
- testForTimeToSplitFormattedLine();
- }
- }
- /**
- * Append a string sequence to the current formatted line.
- * The formattedLine split points are NOT updated.
- * But the formattedLine is checked for time to split.
- *
- * @param sequence the sequence to append.
- * @param canBreakLine if true, a registered line-break
- */
- void ASFormatter::appendSequence(const string& sequence, bool canBreakLine)
- {
- if (canBreakLine && isInLineBreak)
- breakLine();
- formattedLine.append(sequence);
- if (formattedLine.length() > maxCodeLength)
- testForTimeToSplitFormattedLine();
- }
- /**
- * Append an operator sequence to the current formatted line.
- * The formattedLine split points are updated.
- *
- * @param sequence the sequence to append.
- * @param canBreakLine if true, a registered line-break
- */
- void ASFormatter::appendOperator(const string& sequence, bool canBreakLine)
- {
- if (canBreakLine && isInLineBreak)
- breakLine();
- formattedLine.append(sequence);
- if (maxCodeLength != string::npos)
- {
- // These compares reduce the frequency of function calls.
- if (isOkToSplitFormattedLine())
- updateFormattedLineSplitPointsOperator(sequence);
- if (formattedLine.length() > maxCodeLength)
- testForTimeToSplitFormattedLine();
- }
- }
- /**
- * append a space to the current formattedline, UNLESS the
- * last character is already a white-space character.
- */
- void ASFormatter::appendSpacePad()
- {
- int len = formattedLine.length();
- if (len > 0 && !isWhiteSpace(formattedLine[len - 1]))
- {
- formattedLine.append(1, ' ');
- spacePadNum++;
- if (maxCodeLength != string::npos)
- {
- // These compares reduce the frequency of function calls.
- if (isOkToSplitFormattedLine())
- updateFormattedLineSplitPoints(' ');
- if (formattedLine.length() > maxCodeLength)
- testForTimeToSplitFormattedLine();
- }
- }
- }
- /**
- * append a space to the current formattedline, UNLESS the
- * next character is already a white-space character.
- */
- void ASFormatter::appendSpaceAfter()
- {
- int len = currentLine.length();
- if (charNum + 1 < len && !isWhiteSpace(currentLine[charNum + 1]))
- {
- formattedLine.append(1, ' ');
- spacePadNum++;
- if (maxCodeLength != string::npos)
- {
- // These compares reduce the frequency of function calls.
- if (isOkToSplitFormattedLine())
- updateFormattedLineSplitPoints(' ');
- if (formattedLine.length() > maxCodeLength)
- testForTimeToSplitFormattedLine();
- }
- }
- }
- /**
- * register a line break for the formatted line.
- */
- void ASFormatter::breakLine(bool isSplitLine /*false*/)
- {
- isLineReady = true;
- isInLineBreak = false;
- spacePadNum = nextLineSpacePadNum;
- nextLineSpacePadNum = 0;
- readyFormattedLine = formattedLine;
- formattedLine.erase();
- // queue an empty line prepend request if one exists
- prependEmptyLine = isPrependPostBlockEmptyLineRequested;
- if (!isSplitLine)
- {
- formattedLineCommentNum = string::npos;
- clearFormattedLineSplitPoints();
- if (isAppendPostBlockEmptyLineRequested)
- {
- isAppendPostBlockEmptyLineRequested = false;
- isPrependPostBlockEmptyLineRequested = true;
- }
- else
- isPrependPostBlockEmptyLineRequested = false;
- }
- }
- /**
- * check if the currently reached open-brace (i.e. '{')
- * opens a:
- * - a definition type block (such as a class or namespace),
- * - a command block (such as a method block)
- * - a static array
- * this method takes for granted that the current character
- * is an opening brace.
- *
- * @return the type of the opened block.
- */
- BraceType ASFormatter::getBraceType()
- {
- assert(currentChar == '{');
- BraceType returnVal = NULL_TYPE;
- if ((previousNonWSChar == '='
- || isBraceType(braceTypeStack->back(), ARRAY_TYPE))
- && previousCommandChar != ')'
- && !isNonParenHeader)
- returnVal = ARRAY_TYPE;
- else if (foundPreDefinitionHeader && previousCommandChar != ')')
- {
- returnVal = DEFINITION_TYPE;
- if (foundNamespaceHeader)
- returnVal = (BraceType)(returnVal | NAMESPACE_TYPE);
- else if (foundClassHeader)
- returnVal = (BraceType)(returnVal | CLASS_TYPE);
- else if (foundStructHeader)
- returnVal = (BraceType)(returnVal | STRUCT_TYPE);
- else if (foundInterfaceHeader)
- returnVal = (BraceType)(returnVal | INTERFACE_TYPE);
- }
- else if (isInEnum)
- {
- returnVal = (BraceType)(ARRAY_TYPE | ENUM_TYPE);
- }
- else
- {
- bool isCommandType = (foundPreCommandHeader
- || foundPreCommandMacro
- || (currentHeader != nullptr && isNonParenHeader)
- || (previousCommandChar == ')')
- || (previousCommandChar == ':' && !foundQuestionMark)
- || (previousCommandChar == ';')
- || ((previousCommandChar == '{' || previousCommandChar == '}')
- && isPreviousBraceBlockRelated)
- || (isInClassInitializer
- && (!isLegalNameChar(previousNonWSChar) || foundPreCommandHeader))
- || foundTrailingReturnType
- || isInObjCMethodDefinition
- || isInObjCInterface
- || isJavaStaticConstructor
- || isSharpDelegate);
- // C# methods containing 'get', 'set', 'add', and 'remove' do NOT end with parens
- if (!isCommandType && isSharpStyle() && isNextWordSharpNonParenHeader(charNum + 1))
- {
- isCommandType = true;
- isSharpAccessor = true;
- }
- if (isInExternC)
- returnVal = (isCommandType ? COMMAND_TYPE : EXTERN_TYPE);
- else
- returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE);
- }
- int foundOneLineBlock = isOneLineBlockReached(currentLine, charNum);
- if (foundOneLineBlock == 2 && returnVal == COMMAND_TYPE)
- returnVal = ARRAY_TYPE;
- if (foundOneLineBlock > 0)
- {
- returnVal = (BraceType) (returnVal | SINGLE_LINE_TYPE);
- if (breakCurrentOneLineBlock)
- returnVal = (BraceType) (returnVal | BREAK_BLOCK_TYPE);
- if (foundOneLineBlock == 3)
- returnVal = (BraceType)(returnVal | EMPTY_BLOCK_TYPE);
- }
- if (isBraceType(returnVal, ARRAY_TYPE))
- {
- if (isNonInStatementArrayBrace())
- {
- returnVal = (BraceType)(returnVal | ARRAY_NIS_TYPE);
- isNonInStatementArray = true;
- isImmediatelyPostNonInStmt = false; // in case of "},{"
- nonInStatementBrace = formattedLine.length() - 1;
- }
- if (isUniformInitializerBrace())
- returnVal = (BraceType)(returnVal | INIT_TYPE);
- }
- return returnVal;
- }
- /**
- * check if a colon is a class initializer separator
- *
- * @return whether it is a class initializer separator
- */
- bool ASFormatter::isClassInitializer() const
- {
- assert(currentChar == ':');
- assert(previousChar != ':' && peekNextChar() != ':'); // not part of '::'
- // this should be similar to ASBeautifier::parseCurrentLine()
- bool foundClassInitializer = false;
- if (foundQuestionMark)
- {
- // do nothing special
- }
- else if (parenStack->back() > 0)
- {
- // found a 'for' loop or an objective-C statement
- // so do nothing special
- }
- else if (isInEnum)
- {
- // found an enum with a base-type
- }
- else if (isCStyle()
- && !isInCase
- && (previousCommandChar == ')' || foundPreCommandHeader))
- {
- // found a 'class' c'tor initializer
- foundClassInitializer = true;
- }
- return foundClassInitializer;
- }
- /**
- * check if a line is empty
- *
- * @return whether line is empty
- */
- bool ASFormatter::isEmptyLine(const string& line) const
- {
- return line.find_first_not_of(" \t") == string::npos;
- }
- /**
- * Check if the following text is "C" as in extern "C".
- *
- * @return whether the statement is extern "C"
- */
- bool ASFormatter::isExternC() const
- {
- // charNum should be at 'extern'
- assert(!isWhiteSpace(currentLine[charNum]));
- size_t startQuote = currentLine.find_first_of(" \t\"", charNum);
- if (startQuote == string::npos)
- return false;
- startQuote = currentLine.find_first_not_of(" \t", startQuote);
- if (startQuote == string::npos)
- return false;
- if (currentLine.compare(startQuote, 3, "\"C\"") != 0)
- return false;
- return true;
- }
- /**
- * Check if the currently reached '*', '&' or '^' character is
- * a pointer-or-reference symbol, or another operator.
- * A pointer dereference (*) or an "address of" character (&)
- * counts as a pointer or reference because it is not an
- * arithmetic operator.
- *
- * @return whether current character is a reference-or-pointer
- */
- bool ASFormatter::isPointerOrReference() const
- {
- assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
- if (isJavaStyle())
- return false;
- if (isCharImmediatelyPostOperator)
- return false;
- // get the last legal word (may be a number)
- string lastWord = getPreviousWord(currentLine, charNum);
- if (lastWord.empty())
- lastWord = " ";
- // check for preceding or following numeric values
- string nextText = peekNextText(currentLine.substr(charNum + 1));
- if (nextText.length() == 0)
- nextText = " ";
- char nextChar = nextText[0];
- if (isDigit(lastWord[0])
- || isDigit(nextChar)
- || nextChar == '!'
- || nextChar == '~')
- return false;
- // check for multiply then a dereference (a * *b)
- if (currentChar == '*'
- && charNum < (int) currentLine.length() - 1
- && isWhiteSpace(currentLine[charNum + 1])
- && nextChar == '*')
- return false;
- if ((foundCastOperator && nextChar == '>')
- || isPointerOrReferenceVariable(lastWord))
- return true;
- if (isInClassInitializer
- && previousNonWSChar != '('
- && previousNonWSChar != '{'
- && previousCommandChar != ','
- && nextChar != ')'
- && nextChar != '}')
- return false;
- //check for rvalue reference
- if (currentChar == '&' && nextChar == '&')
- {
- if (previousNonWSChar == '>')
- return true;
- string followingText;
- if ((int) currentLine.length() > charNum + 2)
- followingText = peekNextText(currentLine.substr(charNum + 2));
- if (followingText.length() > 0 && followingText[0] == ')')
- return true;
- if (currentHeader != nullptr || isInPotentialCalculation)
- return false;
- if (parenStack->back() > 0 && isBraceType(braceTypeStack->back(), COMMAND_TYPE))
- return false;
- return true;
- }
- if (nextChar == '*'
- || previousNonWSChar == '='
- || previousNonWSChar == '('
- || previousNonWSChar == '['
- || isCharImmediatelyPostReturn
- || isInTemplate
- || isCharImmediatelyPostTemplate
- || currentHeader == &AS_CATCH
- || currentHeader == &AS_FOREACH
- || currentHeader == &AS_QFOREACH)
- return true;
- if (isBraceType(braceTypeStack->back(), ARRAY_TYPE)
- && isLegalNameChar(lastWord[0])
- && isLegalNameChar(nextChar)
- && previousNonWSChar != ')')
- {
- if (isArrayOperator())
- return false;
- }
- // checks on operators in parens
- if (parenStack->back() > 0
- && isLegalNameChar(lastWord[0])
- && isLegalNameChar(nextChar))
- {
- // if followed by an assignment it is a pointer or reference
- // if followed by semicolon it is a pointer or reference in range-based for
- const string* followingOperator = getFollowingOperator();
- if (followingOperator != nullptr
- && followingOperator != &AS_MULT
- && followingOperator != &AS_BIT_AND)
- {
- if (followingOperator == &AS_ASSIGN || followingOperator == &AS_COLON)
- return true;
- return false;
- }
- if (isBraceType(braceTypeStack->back(), COMMAND_TYPE)
- || squareBracketCount > 0)
- return false;
- return true;
- }
- // checks on operators in parens with following '('
- if (parenStack->back() > 0
- && nextChar == '('
- && previousNonWSChar != ','
- && previousNonWSChar != '('
- && previousNonWSChar != '!'
- && previousNonWSChar != '&'
- && previousNonWSChar != '*'
- && previousNonWSChar != '|')
- return false;
- if (nextChar == '-'
- || nextChar == '+')
- {
- size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1);
- if (nextNum != string::npos)
- {
- if (currentLine.compare(nextNum, 2, "++") != 0
- && currentLine.compare(nextNum, 2, "--") != 0)
- return false;
- }
- }
- bool isPR = (!isInPotentialCalculation
- || (!isLegalNameChar(previousNonWSChar)
- && !(previousNonWSChar == ')' && nextChar == '(')
- && !(previousNonWSChar == ')' && currentChar == '*' && !isImmediatelyPostCast())
- && previousNonWSChar != ']')
- || (!isWhiteSpace(nextChar)
- && nextChar != '-'
- && nextChar != '('
- && nextChar != '['
- && !isLegalNameChar(nextChar))
- );
- return isPR;
- }
- /**
- * Check if the currently reached '*' or '&' character is
- * a dereferenced pointer or "address of" symbol.
- * NOTE: this MUST be a pointer or reference as determined by
- * the function isPointerOrReference().
- *
- * @return whether current character is a dereference or address of
- */
- bool ASFormatter::isDereferenceOrAddressOf() const
- {
- assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
- if (isCharImmediatelyPostTemplate)
- return false;
- if (previousNonWSChar == '='
- || previousNonWSChar == ','
- || previousNonWSChar == '.'
- || previousNonWSChar == '{'
- || previousNonWSChar == '>'
- || previousNonWSChar == '<'
- || previousNonWSChar == '?'
- || isCharImmediatelyPostLineComment
- || isCharImmediatelyPostComment
- || isCharImmediatelyPostReturn)
- return true;
- char nextChar = peekNextChar();
- if (currentChar == '*' && nextChar == '*')
- {
- if (previousNonWSChar == '(')
- return true;
- if ((int) currentLine.length() < charNum + 2)
- return true;
- return false;
- }
- if (currentChar == '&' && nextChar == '&')
- {
- if (previousNonWSChar == '(' || isInTemplate)
- return true;
- if ((int) currentLine.length() < charNum + 2)
- return true;
- return false;
- }
- // check first char on the line
- if (charNum == (int) currentLine.find_first_not_of(" \t")
- && (isBraceType(braceTypeStack->back(), COMMAND_TYPE)
- || parenStack->back() != 0))
- return true;
- string nextText = peekNextText(currentLine.substr(charNum + 1));
- if (nextText.length() > 0)
- {
- if (nextText[0] == ')' || nextText[0] == '>'
- || nextText[0] == ',' || nextText[0] == '=')
- return false;
- if (nextText[0] == ';')
- return true;
- }
- // check for reference to a pointer *& (cannot have &*)
- if ((currentChar == '*' && nextChar == '&')
- || (previousNonWSChar == '*' && currentChar == '&'))
- return false;
- if (!isBraceType(braceTypeStack->back(), COMMAND_TYPE)
- && parenStack->back() == 0)
- return false;
- string lastWord = getPreviousWord(currentLine, charNum);
- if (lastWord == "else" || lastWord == "delete")
- return true;
- if (isPointerOrReferenceVariable(lastWord))
- return false;
- bool isDA = (!(isLegalNameChar(previousNonWSChar) || previousNonWSChar == '>')
- || (nextText.length() > 0 && !isLegalNameChar(nextText[0]) && nextText[0] != '/')
- || (ispunct((unsigned char)previousNonWSChar) && previousNonWSChar != '.')
- || isCharImmediatelyPostReturn);
- return isDA;
- }
- /**
- * Check if the currently reached '*' or '&' character is
- * centered with one space on each side.
- * Only spaces are checked, not tabs.
- * If true then a space will be deleted on the output.
- *
- * @return whether current character is centered.
- */
- bool ASFormatter::isPointerOrReferenceCentered() const
- {
- assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
- int prNum = charNum;
- int lineLength = (int) currentLine.length();
- // check for end of line
- if (peekNextChar() == ' ')
- return false;
- // check space before
- if (prNum < 1
- || currentLine[prNum - 1] != ' ')
- return false;
- // check no space before that
- if (prNum < 2
- || currentLine[prNum - 2] == ' ')
- return false;
- // check for ** or &&
- if (prNum + 1 < lineLength
- && (currentLine[prNum + 1] == '*' || currentLine[prNum + 1] == '&'))
- prNum++;
- // check space after
- if (prNum + 1 <= lineLength
- && currentLine[prNum + 1] != ' ')
- return false;
- // check no space after that
- if (prNum + 2 < lineLength
- && currentLine[prNum + 2] == ' ')
- return false;
- return true;
- }
- /**
- * Check if a word is a pointer or reference variable type.
- *
- * @return whether word is a pointer or reference variable.
- */
- bool ASFormatter::isPointerOrReferenceVariable(const string& word) const
- {
- return (word == "char"
- || word == "int"
- || word == "void"
- || (word.length() >= 6 // check end of word for _t
- && word.compare(word.length() - 2, 2, "_t") == 0)
- || word == "INT"
- || word == "VOID");
- }
- /**
- * check if the currently reached '+' or '-' character is a unary operator
- * this method takes for granted that the current character
- * is a '+' or '-'.
- *
- * @return whether the current '+' or '-' is a unary operator.
- */
- bool ASFormatter::isUnaryOperator() const
- {
- assert(currentChar == '+' || currentChar == '-');
- return ((isCharImmediatelyPostReturn || !isLegalNameChar(previousCommandChar))
- && previousCommandChar != '.'
- && previousCommandChar != '\"'
- && previousCommandChar != '\''
- && previousCommandChar != ')'
- && previousCommandChar != ']');
- }
- /**
- * check if the currently reached comment is in a 'switch' statement
- *
- * @return whether the current '+' or '-' is in an exponent.
- */
- bool ASFormatter::isInSwitchStatement() const
- {
- assert(isInLineComment || isInComment);
- if (!preBraceHeaderStack->empty())
- for (size_t i = 1; i < preBraceHeaderStack->size(); i++)
- if (preBraceHeaderStack->at(i) == &AS_SWITCH)
- return true;
- return false;
- }
- /**
- * check if the currently reached '+' or '-' character is
- * part of an exponent, i.e. 0.2E-5.
- *
- * @return whether the current '+' or '-' is in an exponent.
- */
- bool ASFormatter::isInExponent() const
- {
- assert(currentChar == '+' || currentChar == '-');
- if (charNum >= 2)
- {
- char prevPrevFormattedChar = currentLine[charNum - 2];
- char prevFormattedChar = currentLine[charNum - 1];
- return ((prevFormattedChar == 'e' || prevFormattedChar == 'E')
- && (prevPrevFormattedChar == '.' || isDigit(prevPrevFormattedChar)));
- }
- return false;
- }
- /**
- * check if an array brace should NOT have an in-statement indent
- *
- * @return the array is non in-statement
- */
- bool ASFormatter::isNonInStatementArrayBrace() const
- {
- bool returnVal = false;
- char nextChar = peekNextChar();
- // if this opening brace begins the line there will be no inStatement indent
- if (currentLineBeginsWithBrace
- && charNum == (int) currentLineFirstBraceNum
- && nextChar != '}')
- returnVal = true;
- // if an opening brace ends the line there will be no inStatement indent
- if (isWhiteSpace(nextChar)
- || isBeforeAnyLineEndComment(charNum)
- || nextChar == '{')
- returnVal = true;
- // Java "new Type [] {...}" IS an inStatement indent
- if (isJavaStyle() && previousNonWSChar == ']')
- returnVal = false;
- return returnVal;
- }
- /**
- * check if a one-line block has been reached,
- * i.e. if the currently reached '{' character is closed
- * with a complimentary '}' elsewhere on the current line,
- *.
- * @return 0 = one-line block has not been reached.
- * 1 = one-line block has been reached.
- * 2 = one-line block has been reached and is followed by a comma.
- * 3 = one-line block has been reached and is an empty block.
- */
- int ASFormatter::isOneLineBlockReached(const string& line, int startChar) const
- {
- assert(line[startChar] == '{');
- bool isInComment_ = false;
- bool isInQuote_ = false;
- bool hasText = false;
- int braceCount = 0;
- int lineLength = line.length();
- char quoteChar_ = ' ';
- char ch = ' ';
- char prevCh = ' ';
- for (int i = startChar; i < lineLength; ++i)
- {
- ch = line[i];
- if (isInComment_)
- {
- if (line.compare(i, 2, "*/") == 0)
- {
- isInComment_ = false;
- ++i;
- }
- continue;
- }
- if (ch == '\\')
- {
- ++i;
- continue;
- }
- if (isInQuote_)
- {
- if (ch == quoteChar_)
- isInQuote_ = false;
- continue;
- }
- if (ch == '"'
- || (ch == '\'' && !isDigitSeparator(line, i)))
- {
- isInQuote_ = true;
- quoteChar_ = ch;
- continue;
- }
- if (line.compare(i, 2, "//") == 0)
- break;
- if (line.compare(i, 2, "/*") == 0)
- {
- isInComment_ = true;
- ++i;
- continue;
- }
- if (ch == '{')
- {
- ++braceCount;
- continue;
- }
- if (ch == '}')
- {
- --braceCount;
- if (braceCount == 0)
- {
- // is this an array?
- if (parenStack->back() == 0 && prevCh != '}')
- {
- size_t peekNum = line.find_first_not_of(" \t", i + 1);
- if (peekNum != string::npos && line[peekNum] == ',')
- return 2;
- }
- if (!hasText)
- return 3; // is an empty block
- return 1;
- }
- }
- if (ch == ';')
- continue;
- if (!isWhiteSpace(ch))
- {
- hasText = true;
- prevCh = ch;
- }
- }
- return 0;
- }
- /**
- * peek at the next word to determine if it is a C# non-paren header.
- * will look ahead in the input file if necessary.
- *
- * @param startChar position on currentLine to start the search
- * @return true if the next word is get or set.
- */
- bool ASFormatter::isNextWordSharpNonParenHeader(int startChar) const
- {
- // look ahead to find the next non-comment text
- string nextText = peekNextText(currentLine.substr(startChar));
- if (nextText.length() == 0)
- return false;
- if (nextText[0] == '[')
- return true;
- if (!isCharPotentialHeader(nextText, 0))
- return false;
- if (findKeyword(nextText, 0, AS_GET) || findKeyword(nextText, 0, AS_SET)
- || findKeyword(nextText, 0, AS_ADD) || findKeyword(nextText, 0, AS_REMOVE))
- return true;
- return false;
- }
- /**
- * peek at the next char to determine if it is an opening brace.
- * will look ahead in the input file if necessary.
- * this determines a java static constructor.
- *
- * @param startChar position on currentLine to start the search
- * @return true if the next word is an opening brace.
- */
- bool ASFormatter::isNextCharOpeningBrace(int startChar) const
- {
- bool retVal = false;
- string nextText = peekNextText(currentLine.substr(startChar));
- if (nextText.length() > 0
- && nextText.compare(0, 1, "{") == 0)
- retVal = true;
- return retVal;
- }
- /**
- * Check if operator and, pointer, and reference padding is disabled.
- * Disabling is done thru a NOPAD tag in an ending comment.
- *
- * @return true if the formatting on this line is disabled.
- */
- bool ASFormatter::isOperatorPaddingDisabled() const
- {
- size_t commentStart = currentLine.find("//", charNum);
- if (commentStart == string::npos)
- {
- commentStart = currentLine.find("/*", charNum);
- // comment must end on this line
- if (commentStart != string::npos)
- {
- size_t commentEnd = currentLine.find("*/", commentStart + 2);
- if (commentEnd == string::npos)
- commentStart = string::npos;
- }
- }
- if (commentStart == string::npos)
- return false;
- size_t noPadStart = currentLine.find("*NOPAD*", commentStart);
- if (noPadStart == string::npos)
- return false;
- return true;
- }
- /**
- * Determine if an opening array-type brace should have a leading space pad.
- * This is to identify C++11 uniform initializers.
- */
- bool ASFormatter::isUniformInitializerBrace() const
- {
- if (isCStyle() && !isInEnum && !isImmediatelyPostPreprocessor)
- {
- if (isInClassInitializer
- || isLegalNameChar(previousNonWSChar))
- return true;
- }
- return false;
- }
- /**
- * Determine if there is a following statement on the current line.
- */
- bool ASFormatter::isMultiStatementLine() const
- {
- assert((isImmediatelyPostHeader || foundClosingHeader));
- bool isInComment_ = false;
- bool isInQuote_ = false;
- int semiCount_ = 0;
- int parenCount_ = 0;
- int braceCount_ = 0;
- for (size_t i = 0; i < currentLine.length(); i++)
- {
- if (isInComment_)
- {
- if (currentLine.compare(i, 2, "*/") == 0)
- {
- isInComment_ = false;
- continue;
- }
- }
- if (currentLine.compare(i, 2, "/*") == 0)
- {
- isInComment_ = true;
- continue;
- }
- if (currentLine.compare(i, 2, "//") == 0)
- return false;
- if (isInQuote_)
- {
- if (currentLine[i] == '"' || currentLine[i] == '\'')
- isInQuote_ = false;
- continue;
- }
- if (currentLine[i] == '"' || currentLine[i] == '\'')
- {
- isInQuote_ = true;
- continue;
- }
- if (currentLine[i] == '(')
- {
- ++parenCount_;
- continue;
- }
- if (currentLine[i] == ')')
- {
- --parenCount_;
- continue;
- }
- if (parenCount_ > 0)
- continue;
- if (currentLine[i] == '{')
- {
- ++braceCount_;
- }
- if (currentLine[i] == '}')
- {
- --braceCount_;
- }
- if (braceCount_ > 0)
- continue;
- if (currentLine[i] == ';')
- {
- ++semiCount_;
- if (semiCount_ > 1)
- return true;
- continue;
- }
- }
- return false;
- }
- /**
- * get the next non-whitespace substring on following lines, bypassing all comments.
- *
- * @param firstLine the first line to check
- * @return the next non-whitespace substring.
- */
- string ASFormatter::peekNextText(const string& firstLine,
- bool endOnEmptyLine /*false*/,
- shared_ptr<ASPeekStream> streamArg /*nullptr*/) const
- {
- bool isFirstLine = true;
- string nextLine_ = firstLine;
- size_t firstChar = string::npos;
- shared_ptr<ASPeekStream> stream = streamArg;
- if (stream == nullptr) // Borland may need == 0
- stream = make_shared<ASPeekStream>(sourceIterator);
- // find the first non-blank text, bypassing all comments.
- bool isInComment_ = false;
- while (stream->hasMoreLines() || isFirstLine)
- {
- if (isFirstLine)
- isFirstLine = false;
- else
- nextLine_ = stream->peekNextLine();
- firstChar = nextLine_.find_first_not_of(" \t");
- if (firstChar == string::npos)
- {
- if (endOnEmptyLine && !isInComment_)
- break;
- continue;
- }
- if (nextLine_.compare(firstChar, 2, "/*") == 0)
- {
- firstChar += 2;
- isInComment_ = true;
- }
- if (isInComment_)
- {
- firstChar = nextLine_.find("*/", firstChar);
- if (firstChar == string::npos)
- continue;
- firstChar += 2;
- isInComment_ = false;
- firstChar = nextLine_.find_first_not_of(" \t", firstChar);
- if (firstChar == string::npos)
- continue;
- }
- if (nextLine_.compare(firstChar, 2, "//") == 0)
- continue;
- // found the next text
- break;
- }
- if (firstChar == string::npos)
- nextLine_ = "";
- else
- nextLine_ = nextLine_.substr(firstChar);
- return nextLine_;
- }
- /**
- * adjust comment position because of adding or deleting spaces
- * the spaces are added or deleted to formattedLine
- * spacePadNum contains the adjustment
- */
- void ASFormatter::adjustComments()
- {
- assert(spacePadNum != 0);
- assert(isSequenceReached("//") || isSequenceReached("/*"));
- // block comment must be closed on this line with nothing after it
- if (isSequenceReached("/*"))
- {
- size_t endNum = currentLine.find("*/", charNum + 2);
- if (endNum == string::npos)
- return;
- if (currentLine.find_first_not_of(" \t", endNum + 2) != string::npos)
- return;
- }
- size_t len = formattedLine.length();
- // don't adjust a tab
- if (formattedLine[len - 1] == '\t')
- return;
- // if spaces were removed, need to add spaces before the comment
- if (spacePadNum < 0)
- {
- int adjust = -spacePadNum; // make the number positive
- formattedLine.append(adjust, ' ');
- }
- // if spaces were added, need to delete extra spaces before the comment
- // if cannot be done put the comment one space after the last text
- else if (spacePadNum > 0)
- {
- int adjust = spacePadNum;
- size_t lastText = formattedLine.find_last_not_of(' ');
- if (lastText != string::npos
- && lastText < len - adjust - 1)
- formattedLine.resize(len - adjust);
- else if (len > lastText + 2)
- formattedLine.resize(lastText + 2);
- else if (len < lastText + 2)
- formattedLine.append(len - lastText, ' ');
- }
- }
- /**
- * append the current brace inside the end of line comments
- * currentChar contains the brace, it will be appended to formattedLine
- * formattedLineCommentNum is the comment location on formattedLine
- */
- void ASFormatter::appendCharInsideComments()
- {
- if (formattedLineCommentNum == string::npos // does the comment start on the previous line?
- || formattedLineCommentNum == 0)
- {
- appendCurrentChar(); // don't attach
- return;
- }
- assert(formattedLine.compare(formattedLineCommentNum, 2, "//") == 0
- || formattedLine.compare(formattedLineCommentNum, 2, "/*") == 0);
- // find the previous non space char
- size_t end = formattedLineCommentNum;
- size_t beg = formattedLine.find_last_not_of(" \t", end - 1);
- if (beg == string::npos)
- {
- appendCurrentChar(); // don't attach
- return;
- }
- beg++;
- // insert the brace
- if (end - beg < 3) // is there room to insert?
- formattedLine.insert(beg, 3 - end + beg, ' ');
- if (formattedLine[beg] == '\t') // don't pad with a tab
- formattedLine.insert(beg, 1, ' ');
- formattedLine[beg + 1] = currentChar;
- testForTimeToSplitFormattedLine();
- if (isBeforeComment())
- breakLine();
- else if (isCharImmediatelyPostLineComment)
- shouldBreakLineAtNextChar = true;
- }
- /**
- * add or remove space padding to operators
- * the operators and necessary padding will be appended to formattedLine
- * the calling function should have a continue statement after calling this method
- *
- * @param newOperator the operator to be padded
- */
- void ASFormatter::padOperators(const string* newOperator)
- {
- assert(shouldPadOperators);
- assert(newOperator != nullptr);
- char nextNonWSChar = ASBase::peekNextChar(currentLine, charNum);
- bool shouldPad = (newOperator != &AS_SCOPE_RESOLUTION
- && newOperator != &AS_PLUS_PLUS
- && newOperator != &AS_MINUS_MINUS
- && newOperator != &AS_NOT
- && newOperator != &AS_BIT_NOT
- && newOperator != &AS_ARROW
- && !(newOperator == &AS_COLON && !foundQuestionMark // objC methods
- && (isInObjCMethodDefinition || isInObjCInterface
- || isInObjCSelector || squareBracketCount != 0))
- && !(newOperator == &AS_MINUS && isInExponent())
- && !(newOperator == &AS_PLUS && isInExponent())
- && !((newOperator == &AS_PLUS || newOperator == &AS_MINUS) // check for unary plus or minus
- && (previousNonWSChar == '('
- || previousNonWSChar == '['
- || previousNonWSChar == '='
- || previousNonWSChar == ','
- || previousNonWSChar == ':'
- || previousNonWSChar == '{'))
- //? // commented out in release 2.05.1 - doesn't seem to do anything???
- //x && !((newOperator == &AS_MULT || newOperator == &AS_BIT_AND || newOperator == &AS_AND)
- //x && isPointerOrReference())
- && !(newOperator == &AS_MULT
- && (previousNonWSChar == '.'
- || previousNonWSChar == '>')) // check for ->
- && !(newOperator == &AS_MULT && peekNextChar() == '>')
- && !((isInTemplate || isImmediatelyPostTemplate)
- && (newOperator == &AS_LS || newOperator == &AS_GR))
- && !(newOperator == &AS_GCC_MIN_ASSIGN
- && ASBase::peekNextChar(currentLine, charNum + 1) == '>')
- && !(newOperator == &AS_GR && previousNonWSChar == '?')
- && !(newOperator == &AS_QUESTION // check for Java wildcard
- && isJavaStyle()
- && (previousNonWSChar == '<'
- || nextNonWSChar == '>'
- || nextNonWSChar == '.'))
- && !(newOperator == &AS_QUESTION // check for C# null conditional operator
- && isSharpStyle()
- && (nextNonWSChar == '.'
- || nextNonWSChar == '['))
- && !isCharImmediatelyPostOperator
- && !isInCase
- && !isInAsm
- && !isInAsmOneLine
- && !isInAsmBlock
- );
- // pad before operator
- if (shouldPad
- && !(newOperator == &AS_COLON
- && (!foundQuestionMark && !isInEnum) && currentHeader != &AS_FOR)
- && !(newOperator == &AS_QUESTION && isSharpStyle() // check for C# nullable type (e.g. int?)
- && currentLine.find(':', charNum + 1) == string::npos)
- )
- appendSpacePad();
- appendOperator(*newOperator);
- goForward(newOperator->length() - 1);
- currentChar = (*newOperator)[newOperator->length() - 1];
- // pad after operator
- // but do not pad after a '-' that is a unary-minus.
- if (shouldPad
- && !isBeforeAnyComment()
- && !(newOperator == &AS_PLUS && isUnaryOperator())
- && !(newOperator == &AS_MINUS && isUnaryOperator())
- && !(currentLine.compare(charNum + 1, 1, AS_SEMICOLON) == 0)
- && !(currentLine.compare(charNum + 1, 2, AS_SCOPE_RESOLUTION) == 0)
- && !(peekNextChar() == ',')
- && !(newOperator == &AS_QUESTION && isSharpStyle() // check for C# nullable type (e.g. int?)
- && peekNextChar() == '[')
- )
- appendSpaceAfter();
- }
- /**
- * format pointer or reference
- * currentChar contains the pointer or reference
- * the symbol and necessary padding will be appended to formattedLine
- * the calling function should have a continue statement after calling this method
- *
- * NOTE: Do NOT use appendCurrentChar() in this method. The line should not be
- * broken once the calculation starts.
- */
- void ASFormatter::formatPointerOrReference()
- {
- assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
- assert(!isJavaStyle());
- int pa = pointerAlignment;
- int ra = referenceAlignment;
- int itemAlignment = (currentChar == '*' || currentChar == '^') ? pa : ((ra == REF_SAME_AS_PTR) ? pa : ra);
- // check for ** and &&
- int ptrLength = 1;
- char peekedChar = peekNextChar();
- if ((currentChar == '*' && peekedChar == '*')
- || (currentChar == '&' && peekedChar == '&'))
- {
- ptrLength = 2;
- size_t nextChar = currentLine.find_first_not_of(" \t", charNum + 2);
- if (nextChar == string::npos)
- peekedChar = ' ';
- else
- peekedChar = currentLine[nextChar];
- }
- // check for cast
- if (peekedChar == ')' || peekedChar == '>' || peekedChar == ',')
- {
- formatPointerOrReferenceCast();
- return;
- }
- // check for a padded space and remove it
- if (charNum > 0
- && !isWhiteSpace(currentLine[charNum - 1])
- && formattedLine.length() > 0
- && isWhiteSpace(formattedLine[formattedLine.length() - 1]))
- {
- formattedLine.erase(formattedLine.length() - 1);
- spacePadNum--;
- }
- if (itemAlignment == PTR_ALIGN_TYPE)
- {
- formatPointerOrReferenceToType();
- }
- else if (itemAlignment == PTR_ALIGN_MIDDLE)
- {
- formatPointerOrReferenceToMiddle();
- }
- else if (itemAlignment == PTR_ALIGN_NAME)
- {
- formatPointerOrReferenceToName();
- }
- else // pointerAlignment == PTR_ALIGN_NONE
- {
- formattedLine.append(ptrLength, currentChar);
- if (ptrLength > 1)
- goForward(ptrLength - 1);
- }
- }
- /**
- * format pointer or reference with align to type
- */
- void ASFormatter::formatPointerOrReferenceToType()
- {
- assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
- assert(!isJavaStyle());
- // do this before bumping charNum
- bool isOldPRCentered = isPointerOrReferenceCentered();
- size_t prevCh = formattedLine.find_last_not_of(" \t");
- if (prevCh == string::npos)
- prevCh = 0;
- if (formattedLine.length() == 0 || prevCh == formattedLine.length() - 1)
- formattedLine.append(1, currentChar);
- else
- {
- // exchange * or & with character following the type
- // this may not work every time with a tab character
- string charSave = formattedLine.substr(prevCh + 1, 1);
- formattedLine[prevCh + 1] = currentChar;
- formattedLine.append(charSave);
- }
- if (isSequenceReached("**") || isSequenceReached("&&"))
- {
- if (formattedLine.length() == 1)
- formattedLine.append(1, currentChar);
- else
- formattedLine.insert(prevCh + 2, 1, currentChar);
- goForward(1);
- }
- // if no space after then add one
- if (charNum < (int) currentLine.length() - 1
- && !isWhiteSpace(currentLine[charNum + 1])
- && currentLine[charNum + 1] != ')')
- appendSpacePad();
- // if old pointer or reference is centered, remove a space
- if (isOldPRCentered
- && isWhiteSpace(formattedLine[formattedLine.length() - 1]))
- {
- formattedLine.erase(formattedLine.length() - 1, 1);
- spacePadNum--;
- }
- // update the formattedLine split point
- if (maxCodeLength != string::npos)
- {
- size_t index = formattedLine.length() - 1;
- if (isWhiteSpace(formattedLine[index]))
- {
- updateFormattedLineSplitPointsPointerOrReference(index);
- testForTimeToSplitFormattedLine();
- }
- }
- }
- /**
- * format pointer or reference with align in the middle
- */
- void ASFormatter::formatPointerOrReferenceToMiddle()
- {
- assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
- assert(!isJavaStyle());
- // compute current whitespace before
- size_t wsBefore = currentLine.find_last_not_of(" \t", charNum - 1);
- if (wsBefore == string::npos)
- wsBefore = 0;
- else
- wsBefore = charNum - wsBefore - 1;
- string sequenceToInsert(1, currentChar);
- if (isSequenceReached("**"))
- {
- sequenceToInsert = "**";
- goForward(1);
- }
- else if (isSequenceReached("&&"))
- {
- sequenceToInsert = "&&";
- goForward(1);
- }
- // if reference to a pointer check for conflicting alignment
- else if (currentChar == '*' && peekNextChar() == '&'
- && (referenceAlignment == REF_ALIGN_TYPE
- || referenceAlignment == REF_ALIGN_MIDDLE
- || referenceAlignment == REF_SAME_AS_PTR))
- {
- sequenceToInsert = "*&";
- goForward(1);
- for (size_t i = charNum; i < currentLine.length() - 1 && isWhiteSpace(currentLine[i]); i++)
- goForward(1);
- }
- // if a comment follows don't align, just space pad
- if (isBeforeAnyComment())
- {
- appendSpacePad();
- formattedLine.append(sequenceToInsert);
- appendSpaceAfter();
- return;
- }
- // do this before goForward()
- bool isAfterScopeResolution = previousNonWSChar == ':';
- size_t charNumSave = charNum;
- // if this is the last thing on the line
- if (currentLine.find_first_not_of(" \t", charNum + 1) == string::npos)
- {
- if (wsBefore == 0 && !isAfterScopeResolution)
- formattedLine.append(1, ' ');
- formattedLine.append(sequenceToInsert);
- return;
- }
- // goForward() to convert tabs to spaces, if necessary,
- // and move following characters to preceding characters
- // this may not work every time with tab characters
- for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++)
- {
- goForward(1);
- if (formattedLine.length() > 0)
- formattedLine.append(1, currentLine[i]);
- else
- spacePadNum--;
- }
- // find space padding after
- size_t wsAfter = currentLine.find_first_not_of(" \t", charNumSave + 1);
- if (wsAfter == string::npos || isBeforeAnyComment())
- wsAfter = 0;
- else
- wsAfter = wsAfter - charNumSave - 1;
- // don't pad before scope resolution operator, but pad after
- if (isAfterScopeResolution)
- {
- size_t lastText = formattedLine.find_last_not_of(" \t");
- formattedLine.insert(lastText + 1, sequenceToInsert);
- appendSpacePad();
- }
- else if (formattedLine.length() > 0)
- {
- // whitespace should be at least 2 chars to center
- if (wsBefore + wsAfter < 2)
- {
- size_t charsToAppend = (2 - (wsBefore + wsAfter));
- formattedLine.append(charsToAppend, ' ');
- spacePadNum += charsToAppend;
- if (wsBefore == 0)
- wsBefore++;
- if (wsAfter == 0)
- wsAfter++;
- }
- // insert the pointer or reference char
- size_t padAfter = (wsBefore + wsAfter) / 2;
- size_t index = formattedLine.length() - padAfter;
- formattedLine.insert(index, sequenceToInsert);
- }
- else // formattedLine.length() == 0
- {
- formattedLine.append(sequenceToInsert);
- if (wsAfter == 0)
- wsAfter++;
- formattedLine.append(wsAfter, ' ');
- spacePadNum += wsAfter;
- }
- // update the formattedLine split point after the pointer
- if (maxCodeLength != string::npos && formattedLine.length() > 0)
- {
- size_t index = formattedLine.find_last_not_of(" \t");
- if (index != string::npos && (index < formattedLine.length() - 1))
- {
- index++;
- updateFormattedLineSplitPointsPointerOrReference(index);
- testForTimeToSplitFormattedLine();
- }
- }
- }
- /**
- * format pointer or reference with align to name
- */
- void ASFormatter::formatPointerOrReferenceToName()
- {
- assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
- assert(!isJavaStyle());
- // do this before bumping charNum
- bool isOldPRCentered = isPointerOrReferenceCentered();
- size_t startNum = formattedLine.find_last_not_of(" \t");
- if (startNum == string::npos)
- startNum = 0;
- string sequenceToInsert(1, currentChar);
- if (isSequenceReached("**"))
- {
- sequenceToInsert = "**";
- goForward(1);
- }
- else if (isSequenceReached("&&"))
- {
- sequenceToInsert = "&&";
- goForward(1);
- }
- // if reference to a pointer align both to name
- else if (currentChar == '*' && peekNextChar() == '&')
- {
- sequenceToInsert = "*&";
- goForward(1);
- for (size_t i = charNum; i < currentLine.length() - 1 && isWhiteSpace(currentLine[i]); i++)
- goForward(1);
- }
- char peekedChar = peekNextChar();
- bool isAfterScopeResolution = previousNonWSChar == ':'; // check for ::
- // if this is not the last thing on the line
- if (!isBeforeAnyComment()
- && (int) currentLine.find_first_not_of(" \t", charNum + 1) > charNum)
- {
- // goForward() to convert tabs to spaces, if necessary,
- // and move following characters to preceding characters
- // this may not work every time with tab characters
- for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++)
- {
- // if a padded paren follows don't move
- if (shouldPadParensOutside && peekedChar == '(' && !isOldPRCentered)
- {
- // empty parens don't count
- size_t start = currentLine.find_first_not_of("( \t", charNum + 1);
- if (start != string::npos && currentLine[start] != ')')
- break;
- }
- goForward(1);
- if (formattedLine.length() > 0)
- formattedLine.append(1, currentLine[i]);
- else
- spacePadNum--;
- }
- }
- // don't pad before scope resolution operator
- if (isAfterScopeResolution)
- {
- size_t lastText = formattedLine.find_last_not_of(" \t");
- if (lastText != string::npos && lastText + 1 < formattedLine.length())
- formattedLine.erase(lastText + 1);
- }
- // if no space before * then add one
- else if (formattedLine.length() > 0
- && (formattedLine.length() <= startNum + 1
- || !isWhiteSpace(formattedLine[startNum + 1])))
- {
- formattedLine.insert(startNum + 1, 1, ' ');
- spacePadNum++;
- }
- appendSequence(sequenceToInsert, false);
- // if old pointer or reference is centered, remove a space
- if (isOldPRCentered
- && formattedLine.length() > startNum + 1
- && isWhiteSpace(formattedLine[startNum + 1])
- && !isBeforeAnyComment())
- {
- formattedLine.erase(startNum + 1, 1);
- spacePadNum--;
- }
- // don't convert to *= or &=
- if (peekedChar == '=')
- {
- appendSpaceAfter();
- // if more than one space before, delete one
- if (formattedLine.length() > startNum
- && isWhiteSpace(formattedLine[startNum + 1])
- && isWhiteSpace(formattedLine[startNum + 2]))
- {
- formattedLine.erase(startNum + 1, 1);
- spacePadNum--;
- }
- }
- // update the formattedLine split point
- if (maxCodeLength != string::npos)
- {
- size_t index = formattedLine.find_last_of(" \t");
- if (index != string::npos
- && index < formattedLine.length() - 1
- && (formattedLine[index + 1] == '*'
- || formattedLine[index + 1] == '&'
- || formattedLine[index + 1] == '^'))
- {
- updateFormattedLineSplitPointsPointerOrReference(index);
- testForTimeToSplitFormattedLine();
- }
- }
- }
- /**
- * format pointer or reference cast
- * currentChar contains the pointer or reference
- * NOTE: the pointers and references in function definitions
- * are processed as a cast (e.g. void foo(void*, void*))
- * is processed here.
- */
- void ASFormatter::formatPointerOrReferenceCast()
- {
- assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
- assert(!isJavaStyle());
- int pa = pointerAlignment;
- int ra = referenceAlignment;
- int itemAlignment = (currentChar == '*' || currentChar == '^') ? pa : ((ra == REF_SAME_AS_PTR) ? pa : ra);
- string sequenceToInsert(1, currentChar);
- if (isSequenceReached("**") || isSequenceReached("&&"))
- {
- goForward(1);
- sequenceToInsert.append(1, currentLine[charNum]);
- }
- if (itemAlignment == PTR_ALIGN_NONE)
- {
- appendSequence(sequenceToInsert, false);
- return;
- }
- // remove preceding whitespace
- char prevCh = ' ';
- size_t prevNum = formattedLine.find_last_not_of(" \t");
- if (prevNum != string::npos)
- {
- prevCh = formattedLine[prevNum];
- if (prevNum + 1 < formattedLine.length()
- && isWhiteSpace(formattedLine[prevNum + 1])
- && prevCh != '(')
- {
- spacePadNum -= (formattedLine.length() - 1 - prevNum);
- formattedLine.erase(prevNum + 1);
- }
- }
- bool isAfterScopeResolution = previousNonWSChar == ':';
- if ((itemAlignment == PTR_ALIGN_MIDDLE || itemAlignment == PTR_ALIGN_NAME)
- && !isAfterScopeResolution && prevCh != '(')
- {
- appendSpacePad();
- // in this case appendSpacePad may or may not update the split point
- if (maxCodeLength != string::npos && formattedLine.length() > 0)
- updateFormattedLineSplitPointsPointerOrReference(formattedLine.length() - 1);
- appendSequence(sequenceToInsert, false);
- }
- else
- appendSequence(sequenceToInsert, false);
- }
- /**
- * add or remove space padding to parens
- * currentChar contains the paren
- * the parens and necessary padding will be appended to formattedLine
- * the calling function should have a continue statement after calling this method
- */
- void ASFormatter::padParens()
- {
- assert(currentChar == '(' || currentChar == ')');
- assert(shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens || shouldPadFirstParen);
- int spacesOutsideToDelete = 0;
- int spacesInsideToDelete = 0;
- if (currentChar == '(')
- {
- spacesOutsideToDelete = formattedLine.length() - 1;
- spacesInsideToDelete = 0;
- // compute spaces outside the opening paren to delete
- if (shouldUnPadParens)
- {
- char lastChar = ' ';
- bool prevIsParenHeader = false;
- size_t i = formattedLine.find_last_not_of(" \t");
- if (i != string::npos)
- {
- // if last char is a brace the previous whitespace is an indent
- if (formattedLine[i] == '{')
- spacesOutsideToDelete = 0;
- else if (isCharImmediatelyPostPointerOrReference)
- spacesOutsideToDelete = 0;
- else
- {
- spacesOutsideToDelete -= i;
- lastChar = formattedLine[i];
- // if previous word is a header, it will be a paren header
- string prevWord = getPreviousWord(formattedLine, formattedLine.length());
- const string* prevWordH = nullptr;
- if (shouldPadHeader
- && prevWord.length() > 0
- && isCharPotentialHeader(prevWord, 0))
- prevWordH = ASBase::findHeader(prevWord, 0, headers);
- if (prevWordH != nullptr)
- prevIsParenHeader = true;
- else if (prevWord == AS_RETURN) // don't unpad
- prevIsParenHeader = true;
- else if ((prevWord == AS_NEW || prevWord == AS_DELETE)
- && shouldPadHeader) // don't unpad
- prevIsParenHeader = true;
- else if (isCStyle() && prevWord == AS_THROW && shouldPadHeader) // don't unpad
- prevIsParenHeader = true;
- else if (prevWord == "and" || prevWord == "or" || prevWord == "in") // don't unpad
- prevIsParenHeader = true;
- // don't unpad variables
- else if (prevWord == "bool"
- || prevWord == "int"
- || prevWord == "void"
- || prevWord == "void*"
- || prevWord == "char"
- || prevWord == "char*"
- || prevWord == "long"
- || prevWord == "double"
- || prevWord == "float"
- || (prevWord.length() >= 4 // check end of word for _t
- && prevWord.compare(prevWord.length() - 2, 2, "_t") == 0)
- || prevWord == "Int32"
- || prevWord == "UInt32"
- || prevWord == "Int64"
- || prevWord == "UInt64"
- || prevWord == "BOOL"
- || prevWord == "DWORD"
- || prevWord == "HWND"
- || prevWord == "INT"
- || prevWord == "LPSTR"
- || prevWord == "VOID"
- || prevWord == "LPVOID"
- )
- {
- prevIsParenHeader = true;
- }
- }
- }
- // do not unpad operators, but leave them if already padded
- if (shouldPadParensOutside || prevIsParenHeader)
- spacesOutsideToDelete--;
- else if (lastChar == '|' // check for ||
- || lastChar == '&' // check for &&
- || lastChar == ','
- || (lastChar == '(' && shouldPadParensInside)
- || (lastChar == '>' && !foundCastOperator)
- || lastChar == '<'
- || lastChar == '?'
- || lastChar == ':'
- || lastChar == ';'
- || lastChar == '='
- || lastChar == '+'
- || lastChar == '-'
- || lastChar == '*'
- || lastChar == '/'
- || lastChar == '%'
- || lastChar == '^'
- )
- spacesOutsideToDelete--;
- if (spacesOutsideToDelete > 0)
- {
- formattedLine.erase(i + 1, spacesOutsideToDelete);
- spacePadNum -= spacesOutsideToDelete;
- }
- }
- // pad open paren outside
- char peekedCharOutside = peekNextChar();
- if (shouldPadFirstParen && previousChar != '(' && peekedCharOutside != ')')
- appendSpacePad();
- else if (shouldPadParensOutside)
- {
- if (!(currentChar == '(' && peekedCharOutside == ')'))
- appendSpacePad();
- }
- appendCurrentChar();
- // unpad open paren inside
- if (shouldUnPadParens)
- {
- size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
- if (j != string::npos)
- spacesInsideToDelete = j - charNum - 1;
- if (shouldPadParensInside)
- spacesInsideToDelete--;
- if (spacesInsideToDelete > 0)
- {
- currentLine.erase(charNum + 1, spacesInsideToDelete);
- spacePadNum -= spacesInsideToDelete;
- }
- // convert tab to space if requested
- if (shouldConvertTabs
- && (int) currentLine.length() > charNum + 1
- && currentLine[charNum + 1] == '\t')
- currentLine[charNum + 1] = ' ';
- }
- // pad open paren inside
- char peekedCharInside = peekNextChar();
- if (shouldPadParensInside)
- if (!(currentChar == '(' && peekedCharInside == ')'))
- appendSpaceAfter();
- }
- else if (currentChar == ')')
- {
- // unpad close paren inside
- if (shouldUnPadParens)
- {
- spacesInsideToDelete = formattedLine.length();
- size_t i = formattedLine.find_last_not_of(" \t");
- if (i != string::npos)
- spacesInsideToDelete = formattedLine.length() - 1 - i;
- if (shouldPadParensInside)
- spacesInsideToDelete--;
- if (spacesInsideToDelete > 0)
- {
- formattedLine.erase(i + 1, spacesInsideToDelete);
- spacePadNum -= spacesInsideToDelete;
- }
- }
- // pad close paren inside
- if (shouldPadParensInside)
- if (!(previousChar == '(' && currentChar == ')'))
- appendSpacePad();
- appendCurrentChar();
- // unpad close paren outside
- // close parens outside are left unchanged
- if (shouldUnPadParens)
- {
- //spacesOutsideToDelete = 0;
- //size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
- //if (j != string::npos)
- // spacesOutsideToDelete = j - charNum - 1;
- //if (shouldPadParensOutside)
- // spacesOutsideToDelete--;
- //if (spacesOutsideToDelete > 0)
- //{
- // currentLine.erase(charNum + 1, spacesOutsideToDelete);
- // spacePadNum -= spacesOutsideToDelete;
- //}
- }
- // pad close paren outside
- char peekedCharOutside = peekNextChar();
- if (shouldPadParensOutside)
- if (peekedCharOutside != ';'
- && peekedCharOutside != ','
- && peekedCharOutside != '.'
- && peekedCharOutside != '+' // check for ++
- && peekedCharOutside != '-' // check for --
- && peekedCharOutside != ']')
- appendSpaceAfter();
- }
- }
- /**
- * add or remove space padding to objective-c parens
- * these options have precedence over the padParens methods
- * the padParens method has already been called, this method adjusts
- */
- void ASFormatter::padObjCMethodPrefix()
- {
- assert(currentChar == '(' && isImmediatelyPostObjCMethodPrefix);
- assert(shouldPadMethodPrefix || shouldUnPadMethodPrefix);
- size_t prefix = formattedLine.find_first_of("+-");
- if (prefix == string::npos)
- return;
- size_t paren = formattedLine.find_first_of('(');
- if (paren == string::npos)
- return;
- int spaces = paren - prefix - 1;
- if (shouldPadMethodPrefix)
- {
- if (spaces == 0)
- {
- formattedLine.insert(prefix + 1, 1, ' ');
- spacePadNum += 1;
- }
- else if (spaces > 1)
- {
- formattedLine.erase(prefix + 1, spaces - 1);
- spacePadNum -= spaces - 1;
- }
- }
- // this option will be ignored if used with pad-method-prefix
- else if (shouldUnPadMethodPrefix)
- {
- if (spaces > 0)
- {
- formattedLine.erase(prefix + 1, spaces);
- spacePadNum -= spaces;
- }
- }
- }
- /**
- * add or remove space padding to objective-c parens
- * these options have precedence over the padParens methods
- * the padParens method has already been called, this method adjusts
- */
- void ASFormatter::padObjCReturnType()
- {
- assert(currentChar == ')' && isInObjCReturnType);
- assert(shouldPadReturnType || shouldUnPadReturnType);
- size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
- if (nextText == string::npos)
- return;
- int spaces = nextText - charNum - 1;
- if (shouldPadReturnType)
- {
- if (spaces == 0)
- {
- // this will already be padded if pad-paren is used
- if (formattedLine[formattedLine.length() - 1] != ' ')
- {
- formattedLine.append(" ");
- spacePadNum += 1;
- }
- }
- else if (spaces > 1)
- {
- // do not use goForward here
- currentLine.erase(charNum + 1, spaces - 1);
- spacePadNum -= spaces - 1;
- }
- }
- // this option will be ignored if used with pad-return-type
- else if (shouldUnPadReturnType)
- {
- // this will already be padded if pad-paren is used
- if (formattedLine[formattedLine.length() - 1] == ' ')
- {
- spacePadNum -= formattedLine.length() - 1 - nextText;
- int lastText = formattedLine.find_last_not_of(" \t");
- formattedLine.resize(lastText + 1);
- }
- if (spaces > 0)
- {
- // do not use goForward here
- currentLine.erase(charNum + 1, spaces);
- spacePadNum -= spaces;
- }
- }
- }
- /**
- * add or remove space padding to objective-c parens
- * these options have precedence over the padParens methods
- * the padParens method has already been called, this method adjusts
- */
- void ASFormatter::padObjCParamType()
- {
- assert((currentChar == '(' || currentChar == ')') && isInObjCMethodDefinition);
- assert(!isImmediatelyPostObjCMethodPrefix && !isInObjCReturnType);
- assert(shouldPadParamType || shouldUnPadParamType);
- if (currentChar == '(')
- {
- // open paren has already been attached to formattedLine by padParen
- size_t paramOpen = formattedLine.rfind('(');
- assert(paramOpen != string::npos);
- size_t prevText = formattedLine.find_last_not_of(" \t", paramOpen - 1);
- if (prevText == string::npos)
- return;
- int spaces = paramOpen - prevText - 1;
- if (shouldPadParamType
- || objCColonPadMode == COLON_PAD_ALL
- || objCColonPadMode == COLON_PAD_AFTER)
- {
- if (spaces == 0)
- {
- formattedLine.insert(paramOpen, 1, ' ');
- spacePadNum += 1;
- }
- if (spaces > 1)
- {
- formattedLine.erase(prevText + 1, spaces - 1);
- spacePadNum -= spaces - 1;
- }
- }
- // this option will be ignored if used with pad-param-type
- else if (shouldUnPadParamType
- || objCColonPadMode == COLON_PAD_NONE
- || objCColonPadMode == COLON_PAD_BEFORE)
- {
- if (spaces > 0)
- {
- formattedLine.erase(prevText + 1, spaces);
- spacePadNum -= spaces;
- }
- }
- }
- else if (currentChar == ')')
- {
- size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
- if (nextText == string::npos)
- return;
- int spaces = nextText - charNum - 1;
- if (shouldPadParamType)
- {
- if (spaces == 0)
- {
- // this will already be padded if pad-paren is used
- if (formattedLine[formattedLine.length() - 1] != ' ')
- {
- formattedLine.append(" ");
- spacePadNum += 1;
- }
- }
- else if (spaces > 1)
- {
- // do not use goForward here
- currentLine.erase(charNum + 1, spaces - 1);
- spacePadNum -= spaces - 1;
- }
- }
- // this option will be ignored if used with pad-param-type
- else if (shouldUnPadParamType)
- {
- // this will already be padded if pad-paren is used
- if (formattedLine[formattedLine.length() - 1] == ' ')
- {
- spacePadNum -= 1;
- int lastText = formattedLine.find_last_not_of(" \t");
- formattedLine.resize(lastText + 1);
- }
- if (spaces > 0)
- {
- // do not use goForward here
- currentLine.erase(charNum + 1, spaces);
- spacePadNum -= spaces;
- }
- }
- }
- }
- /**
- * format opening brace as attached or broken
- * currentChar contains the brace
- * the braces will be appended to the current formattedLine or a new formattedLine as necessary
- * the calling function should have a continue statement after calling this method
- *
- * @param braceType the type of brace to be formatted.
- */
- void ASFormatter::formatOpeningBrace(BraceType braceType)
- {
- assert(!isBraceType(braceType, ARRAY_TYPE));
- assert(currentChar == '{');
- parenStack->emplace_back(0);
- bool breakBrace = isCurrentBraceBroken();
- if (breakBrace)
- {
- if (isBeforeAnyComment() && isOkToBreakBlock(braceType))
- {
- // if comment is at line end leave the comment on this line
- if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace)
- {
- currentChar = ' '; // remove brace from current line
- if (parenStack->size() > 1)
- parenStack->pop_back();
- currentLine[charNum] = currentChar;
- appendOpeningBrace = true; // append brace to following line
- }
- // else put comment after the brace
- else if (!isBeforeMultipleLineEndComments(charNum))
- breakLine();
- }
- else if (!isBraceType(braceType, SINGLE_LINE_TYPE))
- {
- formattedLine = rtrim(formattedLine);
- breakLine();
- }
- else if ((shouldBreakOneLineBlocks || isBraceType(braceType, BREAK_BLOCK_TYPE))
- && !isBraceType(braceType, EMPTY_BLOCK_TYPE))
- breakLine();
- else if (!isInLineBreak)
- appendSpacePad();
- appendCurrentChar();
- // should a following comment break from the brace?
- // must break the line AFTER the brace
- if (isBeforeComment()
- && formattedLine.length() > 0
- && formattedLine[0] == '{'
- && isOkToBreakBlock(braceType)
- && (braceFormatMode == BREAK_MODE
- || braceFormatMode == LINUX_MODE))
- {
- shouldBreakLineAtNextChar = true;
- }
- }
- else // attach brace
- {
- // are there comments before the brace?
- if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment)
- {
- if (isOkToBreakBlock(braceType)
- && !(isCharImmediatelyPostComment && isCharImmediatelyPostLineComment) // don't attach if two comments on the line
- && !isImmediatelyPostPreprocessor
- // && peekNextChar() != '}' // don't attach { } // removed release 2.03
- && previousCommandChar != '{' // don't attach { {
- && previousCommandChar != '}' // don't attach } {
- && previousCommandChar != ';') // don't attach ; {
- {
- appendCharInsideComments();
- }
- else
- {
- appendCurrentChar(); // don't attach
- }
- }
- else if (previousCommandChar == '{'
- || (previousCommandChar == '}' && !isInClassInitializer)
- || previousCommandChar == ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';'
- {
- appendCurrentChar(); // don't attach
- }
- else
- {
- // if a blank line precedes this don't attach
- if (isEmptyLine(formattedLine))
- appendCurrentChar(); // don't attach
- else if (isOkToBreakBlock(braceType)
- && !(isImmediatelyPostPreprocessor
- && currentLineBeginsWithBrace))
- {
- if (!isBraceType(braceType, EMPTY_BLOCK_TYPE))
- {
- appendSpacePad();
- appendCurrentChar(false); // OK to attach
- testForTimeToSplitFormattedLine(); // line length will have changed
- // should a following comment attach with the brace?
- // insert spaces to reposition the comment
- if (isBeforeComment()
- && !isBeforeMultipleLineEndComments(charNum)
- && (!isBeforeAnyLineEndComment(charNum) || currentLineBeginsWithBrace))
- {
- shouldBreakLineAtNextChar = true;
- currentLine.insert(charNum + 1, charNum + 1, ' ');
- }
- else if (!isBeforeAnyComment()) // added in release 2.03
- {
- shouldBreakLineAtNextChar = true;
- }
- }
- else
- {
- if (currentLineBeginsWithBrace && charNum == (int) currentLineFirstBraceNum)
- {
- appendSpacePad();
- appendCurrentChar(false); // attach
- shouldBreakLineAtNextChar = true;
- }
- else
- {
- appendSpacePad();
- appendCurrentChar(); // don't attach
- }
- }
- }
- else
- {
- if (!isInLineBreak)
- appendSpacePad();
- appendCurrentChar(); // don't attach
- }
- }
- }
- }
- /**
- * format closing brace
- * currentChar contains the brace
- * the calling function should have a continue statement after calling this method
- *
- * @param braceType the type of the opening brace for this closing brace.
- */
- void ASFormatter::formatClosingBrace(BraceType braceType)
- {
- assert(!isBraceType(braceType, ARRAY_TYPE));
- assert(currentChar == '}');
- // parenStack must contain one entry
- if (parenStack->size() > 1)
- parenStack->pop_back();
- // mark state of immediately after empty block
- // this state will be used for locating braces that appear immediately AFTER an empty block (e.g. '{} \n}').
- if (previousCommandChar == '{')
- isImmediatelyPostEmptyBlock = true;
- if (attachClosingBraceMode)
- {
- // for now, namespaces and classes will be attached. Uncomment the lines below to break.
- if ((isEmptyLine(formattedLine) // if a blank line precedes this
- || isCharImmediatelyPostLineComment
- || isCharImmediatelyPostComment
- || (isImmediatelyPostPreprocessor && (int) currentLine.find_first_not_of(" \t") == charNum)
- // || (isBraceType(braceType, CLASS_TYPE) && isOkToBreakBlock(braceType) && previousNonWSChar != '{')
- // || (isBraceType(braceType, NAMESPACE_TYPE) && isOkToBreakBlock(braceType) && previousNonWSChar != '{')
- )
- && (!isBraceType(braceType, SINGLE_LINE_TYPE) || isOkToBreakBlock(braceType)))
- {
- breakLine();
- appendCurrentChar(); // don't attach
- }
- else
- {
- if (previousNonWSChar != '{'
- && (!isBraceType(braceType, SINGLE_LINE_TYPE)
- || isOkToBreakBlock(braceType)))
- appendSpacePad();
- appendCurrentChar(false); // attach
- }
- }
- else if (!isBraceType(braceType, EMPTY_BLOCK_TYPE)
- && (isBraceType(braceType, BREAK_BLOCK_TYPE)
- || isOkToBreakBlock(braceType)))
- {
- breakLine();
- appendCurrentChar();
- }
- else
- {
- appendCurrentChar();
- }
- // if a declaration follows a definition, space pad
- if (isLegalNameChar(peekNextChar()))
- appendSpaceAfter();
- if (shouldBreakBlocks
- && currentHeader != nullptr
- && !isHeaderInMultiStatementLine
- && parenStack->back() == 0)
- {
- if (currentHeader == &AS_CASE || currentHeader == &AS_DEFAULT)
- {
- // do not yet insert a line if "break" statement is outside the braces
- string nextText = peekNextText(currentLine.substr(charNum + 1));
- if (nextText.length() > 0
- && nextText.substr(0, 5) != "break")
- isAppendPostBlockEmptyLineRequested = true;
- }
- else
- isAppendPostBlockEmptyLineRequested = true;
- }
- }
- /**
- * format array braces as attached or broken
- * determine if the braces can have an inStatement indent
- * currentChar contains the brace
- * the braces will be appended to the current formattedLine or a new formattedLine as necessary
- * the calling function should have a continue statement after calling this method
- *
- * @param braceType the type of brace to be formatted, must be an ARRAY_TYPE.
- * @param isOpeningArrayBrace indicates if this is the opening brace for the array block.
- */
- void ASFormatter::formatArrayBraces(BraceType braceType, bool isOpeningArrayBrace)
- {
- assert(isBraceType(braceType, ARRAY_TYPE));
- assert(currentChar == '{' || currentChar == '}');
- if (currentChar == '{')
- {
- // is this the first opening brace in the array?
- if (isOpeningArrayBrace)
- {
- if (braceFormatMode == ATTACH_MODE
- || braceFormatMode == LINUX_MODE)
- {
- // break an enum if mozilla
- if (isBraceType(braceType, ENUM_TYPE)
- && formattingStyle == STYLE_MOZILLA)
- {
- isInLineBreak = true;
- appendCurrentChar(); // don't attach
- }
- // don't attach to a preprocessor directive or '\' line
- else if ((isImmediatelyPostPreprocessor
- || (formattedLine.length() > 0
- && formattedLine[formattedLine.length() - 1] == '\\'))
- && currentLineBeginsWithBrace)
- {
- isInLineBreak = true;
- appendCurrentChar(); // don't attach
- }
- else if (isCharImmediatelyPostComment)
- {
- // TODO: attach brace to line-end comment
- appendCurrentChar(); // don't attach
- }
- else if (isCharImmediatelyPostLineComment && !isBraceType(braceType, SINGLE_LINE_TYPE))
- {
- appendCharInsideComments();
- }
- else
- {
- // if a blank line precedes this don't attach
- if (isEmptyLine(formattedLine))
- appendCurrentChar(); // don't attach
- else
- {
- // if brace is broken or not an assignment
- if (currentLineBeginsWithBrace
- && !isBraceType(braceType, SINGLE_LINE_TYPE))
- {
- appendSpacePad();
- appendCurrentChar(false); // OK to attach
- // TODO: debug the following line
- testForTimeToSplitFormattedLine(); // line length will have changed
- if (currentLineBeginsWithBrace
- && (int) currentLineFirstBraceNum == charNum)
- shouldBreakLineAtNextChar = true;
- }
- else
- {
- if (previousNonWSChar != '(')
- {
- // don't space pad C++11 uniform initialization
- if (!isBraceType(braceType, INIT_TYPE))
- appendSpacePad();
- }
- appendCurrentChar();
- }
- }
- }
- }
- else if (braceFormatMode == BREAK_MODE)
- {
- if (isWhiteSpace(peekNextChar()) && !isInVirginLine)
- breakLine();
- else if (isBeforeAnyComment())
- {
- // do not break unless comment is at line end
- if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace)
- {
- currentChar = ' '; // remove brace from current line
- appendOpeningBrace = true; // append brace to following line
- }
- }
- if (!isInLineBreak && previousNonWSChar != '(')
- {
- // don't space pad C++11 uniform initialization
- if (!isBraceType(braceType, INIT_TYPE))
- appendSpacePad();
- }
- appendCurrentChar();
- if (currentLineBeginsWithBrace
- && (int) currentLineFirstBraceNum == charNum
- && !isBraceType(braceType, SINGLE_LINE_TYPE))
- shouldBreakLineAtNextChar = true;
- }
- else if (braceFormatMode == RUN_IN_MODE)
- {
- if (isWhiteSpace(peekNextChar()) && !isInVirginLine)
- breakLine();
- else if (isBeforeAnyComment())
- {
- // do not break unless comment is at line end
- if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace)
- {
- currentChar = ' '; // remove brace from current line
- appendOpeningBrace = true; // append brace to following line
- }
- }
- if (!isInLineBreak && previousNonWSChar != '(')
- {
- // don't space pad C++11 uniform initialization
- if (!isBraceType(braceType, INIT_TYPE))
- appendSpacePad();
- }
- appendCurrentChar();
- }
- else if (braceFormatMode == NONE_MODE)
- {
- if (currentLineBeginsWithBrace
- && charNum == (int) currentLineFirstBraceNum)
- {
- appendCurrentChar(); // don't attach
- }
- else
- {
- if (previousNonWSChar != '(')
- {
- // don't space pad C++11 uniform initialization
- if (!isBraceType(braceType, INIT_TYPE))
- appendSpacePad();
- }
- appendCurrentChar(false); // OK to attach
- }
- }
- }
- else // not the first opening brace
- {
- if (braceFormatMode == RUN_IN_MODE)
- {
- if (previousNonWSChar == '{'
- && braceTypeStack->size() > 2
- && !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2],
- SINGLE_LINE_TYPE))
- formatArrayRunIn();
- }
- else if (!isInLineBreak
- && !isWhiteSpace(peekNextChar())
- && previousNonWSChar == '{'
- && braceTypeStack->size() > 2
- && !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2],
- SINGLE_LINE_TYPE))
- formatArrayRunIn();
- appendCurrentChar();
- }
- }
- else if (currentChar == '}')
- {
- if (attachClosingBraceMode)
- {
- if (isEmptyLine(formattedLine) // if a blank line precedes this
- || isImmediatelyPostPreprocessor
- || isCharImmediatelyPostLineComment
- || isCharImmediatelyPostComment)
- appendCurrentChar(); // don't attach
- else
- {
- appendSpacePad();
- appendCurrentChar(false); // attach
- }
- }
- else
- {
- // does this close the first opening brace in the array?
- // must check if the block is still a single line because of anonymous statements
- if (!isBraceType(braceType, INIT_TYPE)
- && (!isBraceType(braceType, SINGLE_LINE_TYPE)
- || formattedLine.find('{') == string::npos))
- breakLine();
- appendCurrentChar();
- }
- // if a declaration follows an enum definition, space pad
- char peekedChar = peekNextChar();
- if (isLegalNameChar(peekedChar)
- || peekedChar == '[')
- appendSpaceAfter();
- }
- }
- /**
- * determine if a run-in can be attached.
- * if it can insert the indents in formattedLine and reset the current line break.
- */
- void ASFormatter::formatRunIn()
- {
- assert(braceFormatMode == RUN_IN_MODE || braceFormatMode == NONE_MODE);
- // keep one line blocks returns true without indenting the run-in
- if (formattingStyle != STYLE_PICO
- && !isOkToBreakBlock(braceTypeStack->back()))
- return; // true;
- // make sure the line begins with a brace
- size_t lastText = formattedLine.find_last_not_of(" \t");
- if (lastText == string::npos || formattedLine[lastText] != '{')
- return; // false;
- // make sure the brace is broken
- if (formattedLine.find_first_not_of(" \t{") != string::npos)
- return; // false;
- if (isBraceType(braceTypeStack->back(), NAMESPACE_TYPE))
- return; // false;
- bool extraIndent = false;
- bool extraHalfIndent = false;
- isInLineBreak = true;
- // cannot attach a class modifier without indent-classes
- if (isCStyle()
- && isCharPotentialHeader(currentLine, charNum)
- && (isBraceType(braceTypeStack->back(), CLASS_TYPE)
- || (isBraceType(braceTypeStack->back(), STRUCT_TYPE)
- && isInIndentableStruct)))
- {
- if (findKeyword(currentLine, charNum, AS_PUBLIC)
- || findKeyword(currentLine, charNum, AS_PRIVATE)
- || findKeyword(currentLine, charNum, AS_PROTECTED))
- {
- if (getModifierIndent())
- extraHalfIndent = true;
- else if (!getClassIndent())
- return; // false;
- }
- else if (getClassIndent())
- extraIndent = true;
- }
- // cannot attach a 'case' statement without indent-switches
- if (!getSwitchIndent()
- && isCharPotentialHeader(currentLine, charNum)
- && (findKeyword(currentLine, charNum, AS_CASE)
- || findKeyword(currentLine, charNum, AS_DEFAULT)))
- return; // false;
- // extra indent for switch statements
- if (getSwitchIndent()
- && !preBraceHeaderStack->empty()
- && preBraceHeaderStack->back() == &AS_SWITCH
- && ((isLegalNameChar(currentChar)
- && !findKeyword(currentLine, charNum, AS_CASE))))
- extraIndent = true;
- isInLineBreak = false;
- // remove for extra whitespace
- if (formattedLine.length() > lastText + 1
- && formattedLine.find_first_not_of(" \t", lastText + 1) == string::npos)
- formattedLine.erase(lastText + 1);
- if (extraHalfIndent)
- {
- int indentLength_ = getIndentLength();
- runInIndentChars = indentLength_ / 2;
- formattedLine.append(runInIndentChars - 1, ' ');
- }
- else if (getForceTabIndentation() && getIndentLength() != getTabLength())
- {
- // insert the space indents
- string indent;
- int indentLength_ = getIndentLength();
- int tabLength_ = getTabLength();
- indent.append(indentLength_, ' ');
- if (extraIndent)
- indent.append(indentLength_, ' ');
- // replace spaces indents with tab indents
- size_t tabCount = indent.length() / tabLength_; // truncate extra spaces
- indent.replace(0U, tabCount * tabLength_, tabCount, '\t');
- runInIndentChars = indentLength_;
- if (indent[0] == ' ') // allow for brace
- indent.erase(0, 1);
- formattedLine.append(indent);
- }
- else if (getIndentString() == "\t")
- {
- appendChar('\t', false);
- runInIndentChars = 2; // one for { and one for tab
- if (extraIndent)
- {
- appendChar('\t', false);
- runInIndentChars++;
- }
- }
- else // spaces
- {
- int indentLength_ = getIndentLength();
- formattedLine.append(indentLength_ - 1, ' ');
- runInIndentChars = indentLength_;
- if (extraIndent)
- {
- formattedLine.append(indentLength_, ' ');
- runInIndentChars += indentLength_;
- }
- }
- isInBraceRunIn = true;
- }
- /**
- * remove whitespace and add indentation for an array run-in.
- */
- void ASFormatter::formatArrayRunIn()
- {
- assert(isBraceType(braceTypeStack->back(), ARRAY_TYPE));
- // make sure the brace is broken
- if (formattedLine.find_first_not_of(" \t{") != string::npos)
- return;
- size_t lastText = formattedLine.find_last_not_of(" \t");
- if (lastText == string::npos || formattedLine[lastText] != '{')
- return;
- // check for extra whitespace
- if (formattedLine.length() > lastText + 1
- && formattedLine.find_first_not_of(" \t", lastText + 1) == string::npos)
- formattedLine.erase(lastText + 1);
- if (getIndentString() == "\t")
- {
- appendChar('\t', false);
- runInIndentChars = 2; // one for { and one for tab
- }
- else
- {
- int indent = getIndentLength();
- formattedLine.append(indent - 1, ' ');
- runInIndentChars = indent;
- }
- isInBraceRunIn = true;
- isInLineBreak = false;
- }
- /**
- * delete a braceTypeStack vector object
- * BraceTypeStack did not work with the DeleteContainer template
- */
- void ASFormatter::deleteContainer(vector<BraceType>*& container)
- {
- if (container != nullptr)
- {
- container->clear();
- delete (container);
- container = nullptr;
- }
- }
- /**
- * delete a vector object
- * T is the type of vector
- * used for all vectors except braceTypeStack
- */
- template<typename T>
- void ASFormatter::deleteContainer(T& container)
- {
- if (container != nullptr)
- {
- container->clear();
- delete (container);
- container = nullptr;
- }
- }
- /**
- * initialize a braceType vector object
- * braceType did not work with the DeleteContainer template
- */
- void ASFormatter::initContainer(vector<BraceType>*& container, vector<BraceType>* value)
- {
- if (container != nullptr)
- deleteContainer(container);
- container = value;
- }
- /**
- * initialize a vector object
- * T is the type of vector
- * used for all vectors except braceTypeStack
- */
- template<typename T>
- void ASFormatter::initContainer(T& container, T value)
- {
- // since the ASFormatter object is never deleted,
- // the existing vectors must be deleted before creating new ones
- if (container != nullptr)
- deleteContainer(container);
- container = value;
- }
- /**
- * convert a tab to spaces.
- * charNum points to the current character to convert to spaces.
- * tabIncrementIn is the increment that must be added for tab indent characters
- * to get the correct column for the current tab.
- * replaces the tab in currentLine with the required number of spaces.
- * replaces the value of currentChar.
- */
- void ASFormatter::convertTabToSpaces()
- {
- assert(currentChar == '\t');
- // do NOT replace if in quotes
- if (isInQuote || isInQuoteContinuation)
- return;
- size_t tabSize = getTabLength();
- size_t numSpaces = tabSize - ((tabIncrementIn + charNum) % tabSize);
- currentLine.replace(charNum, 1, numSpaces, ' ');
- currentChar = currentLine[charNum];
- }
- /**
- * is it ok to break this block?
- */
- bool ASFormatter::isOkToBreakBlock(BraceType braceType) const
- {
- // Actually, there should not be an ARRAY_TYPE brace here.
- // But this will avoid breaking a one line block when there is.
- // Otherwise they will be formatted differently on consecutive runs.
- if (isBraceType(braceType, ARRAY_TYPE)
- && isBraceType(braceType, SINGLE_LINE_TYPE))
- return false;
- if (isBraceType(braceType, COMMAND_TYPE)
- && isBraceType(braceType, EMPTY_BLOCK_TYPE))
- return false;
- if (!isBraceType(braceType, SINGLE_LINE_TYPE)
- || isBraceType(braceType, BREAK_BLOCK_TYPE)
- || shouldBreakOneLineBlocks)
- return true;
- return false;
- }
- /**
- * check if a sharp header is a paren or non-paren header
- */
- bool ASFormatter::isSharpStyleWithParen(const string* header) const
- {
- return (isSharpStyle() && peekNextChar() == '('
- && (header == &AS_CATCH
- || header == &AS_DELEGATE));
- }
- /**
- * Check for a following header when a comment is reached.
- * firstLine must contain the start of the comment.
- * return value is a pointer to the header or nullptr.
- */
- const string* ASFormatter::checkForHeaderFollowingComment(const string& firstLine) const
- {
- assert(isInComment || isInLineComment);
- assert(shouldBreakElseIfs || shouldBreakBlocks || isInSwitchStatement());
- // look ahead to find the next non-comment text
- bool endOnEmptyLine = (currentHeader == nullptr);
- if (isInSwitchStatement())
- endOnEmptyLine = false;
- string nextText = peekNextText(firstLine, endOnEmptyLine);
- if (nextText.length() == 0 || !isCharPotentialHeader(nextText, 0))
- return nullptr;
- return ASBase::findHeader(nextText, 0, headers);
- }
- /**
- * process preprocessor statements.
- * charNum should be the index of the #.
- *
- * delete braceTypeStack entries added by #if if a #else is found.
- * prevents double entries in the braceTypeStack.
- */
- void ASFormatter::processPreprocessor()
- {
- assert(currentChar == '#');
- const size_t preproc = currentLine.find_first_not_of(" \t", charNum + 1);
- if (preproc == string::npos)
- return;
- if (currentLine.compare(preproc, 2, "if") == 0)
- {
- preprocBraceTypeStackSize = braceTypeStack->size();
- }
- else if (currentLine.compare(preproc, 4, "else") == 0)
- {
- // delete stack entries added in #if
- // should be replaced by #else
- if (preprocBraceTypeStackSize > 0)
- {
- int addedPreproc = braceTypeStack->size() - preprocBraceTypeStackSize;
- for (int i = 0; i < addedPreproc; i++)
- braceTypeStack->pop_back();
- }
- }
- }
- /**
- * determine if the next line starts a comment
- * and a header follows the comment or comments.
- */
- bool ASFormatter::commentAndHeaderFollows()
- {
- // called ONLY IF shouldDeleteEmptyLines and shouldBreakBlocks are TRUE.
- assert(shouldDeleteEmptyLines && shouldBreakBlocks);
- // is the next line a comment
- auto stream = make_shared<ASPeekStream>(sourceIterator);
- if (!stream->hasMoreLines())
- return false;
- string nextLine_ = stream->peekNextLine();
- size_t firstChar = nextLine_.find_first_not_of(" \t");
- if (firstChar == string::npos
- || !(nextLine_.compare(firstChar, 2, "//") == 0
- || nextLine_.compare(firstChar, 2, "/*") == 0))
- return false;
- // find the next non-comment text, and reset
- string nextText = peekNextText(nextLine_, false, stream);
- if (nextText.length() == 0 || !isCharPotentialHeader(nextText, 0))
- return false;
- const string* newHeader = ASBase::findHeader(nextText, 0, headers);
- if (newHeader == nullptr)
- return false;
- // if a closing header, reset break unless break is requested
- if (isClosingHeader(newHeader) && !shouldBreakClosingHeaderBlocks)
- {
- isAppendPostBlockEmptyLineRequested = false;
- return false;
- }
- return true;
- }
- /**
- * determine if a brace should be attached or broken
- * uses braces in the braceTypeStack
- * the last brace in the braceTypeStack is the one being formatted
- * returns true if the brace should be broken
- */
- bool ASFormatter::isCurrentBraceBroken() const
- {
- assert(braceTypeStack->size() > 1);
- bool breakBrace = false;
- size_t stackEnd = braceTypeStack->size() - 1;
- // check brace modifiers
- if (shouldAttachExternC
- && isBraceType((*braceTypeStack)[stackEnd], EXTERN_TYPE))
- {
- return false;
- }
- if (shouldAttachNamespace
- && isBraceType((*braceTypeStack)[stackEnd], NAMESPACE_TYPE))
- {
- return false;
- }
- if (shouldAttachClass
- && (isBraceType((*braceTypeStack)[stackEnd], CLASS_TYPE)
- || isBraceType((*braceTypeStack)[stackEnd], INTERFACE_TYPE)))
- {
- return false;
- }
- if (shouldAttachInline
- && isCStyle() // for C++ only
- && braceFormatMode != RUN_IN_MODE
- && !(currentLineBeginsWithBrace && peekNextChar() == '/')
- && isBraceType((*braceTypeStack)[stackEnd], COMMAND_TYPE))
- {
- size_t i;
- for (i = 1; i < braceTypeStack->size(); i++)
- if (isBraceType((*braceTypeStack)[i], CLASS_TYPE)
- || isBraceType((*braceTypeStack)[i], STRUCT_TYPE))
- return false;
- }
- // check braces
- if (isBraceType((*braceTypeStack)[stackEnd], EXTERN_TYPE))
- {
- if (currentLineBeginsWithBrace
- || braceFormatMode == RUN_IN_MODE)
- breakBrace = true;
- }
- else if (braceFormatMode == NONE_MODE)
- {
- if (currentLineBeginsWithBrace
- && (int) currentLineFirstBraceNum == charNum)
- breakBrace = true;
- }
- else if (braceFormatMode == BREAK_MODE || braceFormatMode == RUN_IN_MODE)
- {
- breakBrace = true;
- }
- else if (braceFormatMode == LINUX_MODE)
- {
- // break a namespace if NOT stroustrup or mozilla
- if (isBraceType((*braceTypeStack)[stackEnd], NAMESPACE_TYPE))
- {
- if (formattingStyle != STYLE_STROUSTRUP
- && formattingStyle != STYLE_MOZILLA)
- breakBrace = true;
- }
- // break a class or interface if NOT stroustrup
- else if (isBraceType((*braceTypeStack)[stackEnd], CLASS_TYPE)
- || isBraceType((*braceTypeStack)[stackEnd], INTERFACE_TYPE))
- {
- if (formattingStyle != STYLE_STROUSTRUP)
- breakBrace = true;
- }
- // break a struct if mozilla - an enum is processed as an array brace
- else if (isBraceType((*braceTypeStack)[stackEnd], STRUCT_TYPE))
- {
- if (formattingStyle == STYLE_MOZILLA)
- breakBrace = true;
- }
- // break the first brace if a function
- else if (isBraceType((*braceTypeStack)[stackEnd], COMMAND_TYPE))
- {
- if (stackEnd == 1)
- {
- breakBrace = true;
- }
- else if (stackEnd > 1)
- {
- // break the first brace after these if a function
- if (isBraceType((*braceTypeStack)[stackEnd - 1], NAMESPACE_TYPE)
- || isBraceType((*braceTypeStack)[stackEnd - 1], CLASS_TYPE)
- || isBraceType((*braceTypeStack)[stackEnd - 1], ARRAY_TYPE)
- || isBraceType((*braceTypeStack)[stackEnd - 1], STRUCT_TYPE)
- || isBraceType((*braceTypeStack)[stackEnd - 1], EXTERN_TYPE))
- {
- breakBrace = true;
- }
- }
- }
- }
- return breakBrace;
- }
- /**
- * format comment body
- * the calling function should have a continue statement after calling this method
- */
- void ASFormatter::formatCommentBody()
- {
- assert(isInComment);
- // append the comment
- while (charNum < (int) currentLine.length())
- {
- currentChar = currentLine[charNum];
- if (isSequenceReached("*/"))
- {
- formatCommentCloser();
- break;
- }
- if (currentChar == '\t' && shouldConvertTabs)
- convertTabToSpaces();
- appendCurrentChar();
- ++charNum;
- }
- if (shouldStripCommentPrefix)
- stripCommentPrefix();
- }
- /**
- * format a comment opener
- * the comment opener will be appended to the current formattedLine or a new formattedLine as necessary
- * the calling function should have a continue statement after calling this method
- */
- void ASFormatter::formatCommentOpener()
- {
- assert(isSequenceReached("/*"));
- isInComment = isInCommentStartLine = true;
- isImmediatelyPostLineComment = false;
- if (previousNonWSChar == '}')
- resetEndOfStatement();
- // Check for a following header.
- // For speed do not check multiple comment lines more than once.
- // For speed do not check shouldBreakBlocks if previous line is empty, a comment, or a '{'.
- const string* followingHeader = nullptr;
- if ((doesLineStartComment
- && !isImmediatelyPostCommentOnly
- && isBraceType(braceTypeStack->back(), COMMAND_TYPE))
- && (shouldBreakElseIfs
- || isInSwitchStatement()
- || (shouldBreakBlocks
- && !isImmediatelyPostEmptyLine
- && previousCommandChar != '{')))
- followingHeader = checkForHeaderFollowingComment(currentLine.substr(charNum));
- if (spacePadNum != 0 && !isInLineBreak)
- adjustComments();
- formattedLineCommentNum = formattedLine.length();
- // must be done BEFORE appendSequence
- if (previousCommandChar == '{'
- && !isImmediatelyPostComment
- && !isImmediatelyPostLineComment)
- {
- if (isBraceType(braceTypeStack->back(), NAMESPACE_TYPE))
- {
- // namespace run-in is always broken.
- isInLineBreak = true;
- }
- else if (braceFormatMode == NONE_MODE)
- {
- // should a run-in statement be attached?
- if (currentLineBeginsWithBrace)
- formatRunIn();
- }
- else if (braceFormatMode == ATTACH_MODE)
- {
- // if the brace was not attached?
- if (formattedLine.length() > 0 && formattedLine[0] == '{'
- && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE))
- isInLineBreak = true;
- }
- else if (braceFormatMode == RUN_IN_MODE)
- {
- // should a run-in statement be attached?
- if (formattedLine.length() > 0 && formattedLine[0] == '{')
- formatRunIn();
- }
- }
- else if (!doesLineStartComment)
- noTrimCommentContinuation = true;
- // ASBeautifier needs to know the following statements
- if (shouldBreakElseIfs && followingHeader == &AS_ELSE)
- elseHeaderFollowsComments = true;
- if (followingHeader == &AS_CASE || followingHeader == &AS_DEFAULT)
- caseHeaderFollowsComments = true;
- // appendSequence will write the previous line
- appendSequence(AS_OPEN_COMMENT);
- goForward(1);
- // must be done AFTER appendSequence
- // Break before the comment if a header follows the line comment.
- // But not break if previous line is empty, a comment, or a '{'.
- if (shouldBreakBlocks
- && followingHeader != nullptr
- && !isImmediatelyPostEmptyLine
- && previousCommandChar != '{')
- {
- if (isClosingHeader(followingHeader))
- {
- if (!shouldBreakClosingHeaderBlocks)
- isPrependPostBlockEmptyLineRequested = false;
- }
- // if an opening header, break before the comment
- else
- isPrependPostBlockEmptyLineRequested = true;
- }
- if (previousCommandChar == '}')
- currentHeader = nullptr;
- }
- /**
- * format a comment closer
- * the comment closer will be appended to the current formattedLine
- */
- void ASFormatter::formatCommentCloser()
- {
- assert(isSequenceReached("*/"));
- isInComment = false;
- noTrimCommentContinuation = false;
- isImmediatelyPostComment = true;
- appendSequence(AS_CLOSE_COMMENT);
- goForward(1);
- if (doesLineStartComment
- && (currentLine.find_first_not_of(" \t", charNum + 1) == string::npos))
- lineEndsInCommentOnly = true;
- if (peekNextChar() == '}'
- && previousCommandChar != ';'
- && !isBraceType(braceTypeStack->back(), ARRAY_TYPE)
- && !isInPreprocessor
- && isOkToBreakBlock(braceTypeStack->back()))
- {
- isInLineBreak = true;
- shouldBreakLineAtNextChar = true;
- }
- }
- /**
- * format a line comment body
- * the calling function should have a continue statement after calling this method
- */
- void ASFormatter::formatLineCommentBody()
- {
- assert(isInLineComment);
- // append the comment
- while (charNum < (int) currentLine.length())
- // && !isLineReady // commented out in release 2.04, unnecessary
- {
- currentChar = currentLine[charNum];
- if (currentChar == '\t' && shouldConvertTabs)
- convertTabToSpaces();
- appendCurrentChar();
- ++charNum;
- }
- // explicitly break a line when a line comment's end is found.
- if (charNum == (int) currentLine.length())
- {
- isInLineBreak = true;
- isInLineComment = false;
- isImmediatelyPostLineComment = true;
- currentChar = 0; //make sure it is a neutral char.
- }
- }
- /**
- * format a line comment opener
- * the line comment opener will be appended to the current formattedLine or a new formattedLine as necessary
- * the calling function should have a continue statement after calling this method
- */
- void ASFormatter::formatLineCommentOpener()
- {
- assert(isSequenceReached("//"));
- if ((int) currentLine.length() > charNum + 2
- && currentLine[charNum + 2] == '\xf2') // check for windows line marker
- isAppendPostBlockEmptyLineRequested = false;
- isInLineComment = true;
- isCharImmediatelyPostComment = false;
- if (previousNonWSChar == '}')
- resetEndOfStatement();
- // Check for a following header.
- // For speed do not check multiple comment lines more than once.
- // For speed do not check shouldBreakBlocks if previous line is empty, a comment, or a '{'.
- const string* followingHeader = nullptr;
- if ((lineIsLineCommentOnly
- && !isImmediatelyPostCommentOnly
- && isBraceType(braceTypeStack->back(), COMMAND_TYPE))
- && (shouldBreakElseIfs
- || isInSwitchStatement()
- || (shouldBreakBlocks
- && !isImmediatelyPostEmptyLine
- && previousCommandChar != '{')))
- followingHeader = checkForHeaderFollowingComment(currentLine.substr(charNum));
- // do not indent if in column 1 or 2
- // or in a namespace before the opening brace
- if ((!shouldIndentCol1Comments && !lineCommentNoIndent)
- || foundNamespaceHeader)
- {
- if (charNum == 0)
- lineCommentNoIndent = true;
- else if (charNum == 1 && currentLine[0] == ' ')
- lineCommentNoIndent = true;
- }
- // move comment if spaces were added or deleted
- if (!lineCommentNoIndent && spacePadNum != 0 && !isInLineBreak)
- adjustComments();
- formattedLineCommentNum = formattedLine.length();
- // must be done BEFORE appendSequence
- // check for run-in statement
- if (previousCommandChar == '{'
- && !isImmediatelyPostComment
- && !isImmediatelyPostLineComment)
- {
- if (braceFormatMode == NONE_MODE)
- {
- if (currentLineBeginsWithBrace)
- formatRunIn();
- }
- else if (braceFormatMode == RUN_IN_MODE)
- {
- if (!lineCommentNoIndent)
- formatRunIn();
- else
- isInLineBreak = true;
- }
- else if (braceFormatMode == BREAK_MODE)
- {
- if (formattedLine.length() > 0 && formattedLine[0] == '{')
- isInLineBreak = true;
- }
- else
- {
- if (currentLineBeginsWithBrace)
- isInLineBreak = true;
- }
- }
- // ASBeautifier needs to know the following statements
- if (shouldBreakElseIfs && followingHeader == &AS_ELSE)
- elseHeaderFollowsComments = true;
- if (followingHeader == &AS_CASE || followingHeader == &AS_DEFAULT)
- caseHeaderFollowsComments = true;
- // appendSequence will write the previous line
- appendSequence(AS_OPEN_LINE_COMMENT);
- goForward(1);
- // must be done AFTER appendSequence
- // Break before the comment if a header follows the line comment.
- // But do not break if previous line is empty, a comment, or a '{'.
- if (shouldBreakBlocks
- && followingHeader != nullptr
- && !isImmediatelyPostEmptyLine
- && previousCommandChar != '{')
- {
- if (isClosingHeader(followingHeader))
- {
- if (!shouldBreakClosingHeaderBlocks)
- isPrependPostBlockEmptyLineRequested = false;
- }
- // if an opening header, break before the comment
- else
- isPrependPostBlockEmptyLineRequested = true;
- }
- if (previousCommandChar == '}')
- currentHeader = nullptr;
- // if tabbed input don't convert the immediately following tabs to spaces
- if (getIndentString() == "\t" && lineCommentNoIndent)
- {
- while (charNum + 1 < (int) currentLine.length()
- && currentLine[charNum + 1] == '\t')
- {
- currentChar = currentLine[++charNum];
- appendCurrentChar();
- }
- }
- // explicitly break a line when a line comment's end is found.
- if (charNum + 1 == (int) currentLine.length())
- {
- isInLineBreak = true;
- isInLineComment = false;
- isImmediatelyPostLineComment = true;
- currentChar = 0; //make sure it is a neutral char.
- }
- }
- /**
- * format quote body
- * the calling function should have a continue statement after calling this method
- */
- void ASFormatter::formatQuoteBody()
- {
- assert(isInQuote);
- if (isSpecialChar)
- {
- isSpecialChar = false;
- }
- else if (currentChar == '\\' && !isInVerbatimQuote)
- {
- if (peekNextChar() == ' ') // is this '\' at end of line
- haveLineContinuationChar = true;
- else
- isSpecialChar = true;
- }
- else if (isInVerbatimQuote && currentChar == '"')
- {
- if (isCStyle())
- {
- string delim = ')' + verbatimDelimiter;
- int delimStart = charNum - delim.length();
- if (delimStart > 0 && currentLine.substr(delimStart, delim.length()) == delim)
- {
- isInQuote = false;
- isInVerbatimQuote = false;
- }
- }
- else if (isSharpStyle())
- {
- if ((int) currentLine.length() > charNum + 1
- && currentLine[charNum + 1] == '"') // check consecutive quotes
- {
- appendSequence("\"\"");
- goForward(1);
- return;
- }
- isInQuote = false;
- isInVerbatimQuote = false;
- }
- }
- else if (quoteChar == currentChar)
- {
- isInQuote = false;
- }
- appendCurrentChar();
- // append the text to the ending quoteChar or an escape sequence
- // tabs in quotes are NOT changed by convert-tabs
- if (isInQuote && currentChar != '\\')
- {
- while (charNum + 1 < (int) currentLine.length()
- && currentLine[charNum + 1] != quoteChar
- && currentLine[charNum + 1] != '\\')
- {
- currentChar = currentLine[++charNum];
- appendCurrentChar();
- }
- }
- if (charNum + 1 >= (int) currentLine.length()
- && currentChar != '\\'
- && !isInVerbatimQuote)
- isInQuote = false; // missing closing quote
- }
- /**
- * format a quote opener
- * the quote opener will be appended to the current formattedLine or a new formattedLine as necessary
- * the calling function should have a continue statement after calling this method
- */
- void ASFormatter::formatQuoteOpener()
- {
- assert(currentChar == '"'
- || (currentChar == '\'' && !isDigitSeparator(currentLine, charNum)));
- isInQuote = true;
- quoteChar = currentChar;
- if (isCStyle() && previousChar == 'R')
- {
- int parenPos = currentLine.find('(', charNum);
- if (parenPos != -1)
- {
- isInVerbatimQuote = true;
- verbatimDelimiter = currentLine.substr(charNum + 1, parenPos - charNum - 1);
- }
- }
- else if (isSharpStyle() && previousChar == '@')
- isInVerbatimQuote = true;
- // a quote following a brace is an array
- if (previousCommandChar == '{'
- && !isImmediatelyPostComment
- && !isImmediatelyPostLineComment
- && isNonInStatementArray
- && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
- && !isWhiteSpace(peekNextChar()))
- {
- if (braceFormatMode == NONE_MODE)
- {
- if (currentLineBeginsWithBrace)
- formatRunIn();
- }
- else if (braceFormatMode == RUN_IN_MODE)
- {
- formatRunIn();
- }
- else if (braceFormatMode == BREAK_MODE)
- {
- if (formattedLine.length() > 0 && formattedLine[0] == '{')
- isInLineBreak = true;
- }
- else
- {
- if (currentLineBeginsWithBrace)
- isInLineBreak = true;
- }
- }
- previousCommandChar = ' ';
- appendCurrentChar();
- }
- /**
- * get the next line comment adjustment that results from breaking a closing brace.
- * the brace must be on the same line as the closing header.
- * i.e "} else" changed to "} <NL> else".
- */
- int ASFormatter::getNextLineCommentAdjustment()
- {
- assert(foundClosingHeader && previousNonWSChar == '}');
- if (charNum < 1) // "else" is in column 1
- return 0;
- size_t lastBrace = currentLine.rfind('}', charNum - 1);
- if (lastBrace != string::npos)
- return (lastBrace - charNum); // return a negative number
- return 0;
- }
- // for console build only
- LineEndFormat ASFormatter::getLineEndFormat() const
- {
- return lineEnd;
- }
- /**
- * get the current line comment adjustment that results from attaching
- * a closing header to a closing brace.
- * the brace must be on the line previous to the closing header.
- * the adjustment is 2 chars, one for the brace and one for the space.
- * i.e "} <NL> else" changed to "} else".
- */
- int ASFormatter::getCurrentLineCommentAdjustment()
- {
- assert(foundClosingHeader && previousNonWSChar == '}');
- if (charNum < 1)
- return 2;
- size_t lastBrace = currentLine.rfind('}', charNum - 1);
- if (lastBrace == string::npos)
- return 2;
- return 0;
- }
- /**
- * get the previous word on a line
- * the argument 'currPos' must point to the current position.
- *
- * @return is the previous word or an empty string if none found.
- */
- string ASFormatter::getPreviousWord(const string& line, int currPos) const
- {
- // get the last legal word (may be a number)
- if (currPos == 0)
- return string();
- size_t end = line.find_last_not_of(" \t", currPos - 1);
- if (end == string::npos || !isLegalNameChar(line[end]))
- return string();
- int start; // start of the previous word
- for (start = end; start > -1; start--)
- {
- if (!isLegalNameChar(line[start]) || line[start] == '.')
- break;
- }
- start++;
- return (line.substr(start, end - start + 1));
- }
- /**
- * check if a line break is needed when a closing brace
- * is followed by a closing header.
- * the break depends on the braceFormatMode and other factors.
- */
- void ASFormatter::isLineBreakBeforeClosingHeader()
- {
- assert(foundClosingHeader && previousNonWSChar == '}');
- if (currentHeader == &AS_WHILE && shouldAttachClosingWhile)
- {
- appendClosingHeader();
- return;
- }
- if (braceFormatMode == BREAK_MODE
- || braceFormatMode == RUN_IN_MODE
- || attachClosingBraceMode)
- {
- isInLineBreak = true;
- }
- else if (braceFormatMode == NONE_MODE)
- {
- if (shouldBreakClosingHeaderBraces
- || getBraceIndent() || getBlockIndent())
- {
- isInLineBreak = true;
- }
- else
- {
- appendSpacePad();
- // is closing brace broken?
- size_t i = currentLine.find_first_not_of(" \t");
- if (i != string::npos && currentLine[i] == '}')
- isInLineBreak = false;
- if (shouldBreakBlocks)
- isAppendPostBlockEmptyLineRequested = false;
- }
- }
- // braceFormatMode == ATTACH_MODE, LINUX_MODE
- else
- {
- if (shouldBreakClosingHeaderBraces
- || getBraceIndent() || getBlockIndent())
- {
- isInLineBreak = true;
- }
- else
- {
- appendClosingHeader();
- if (shouldBreakBlocks)
- isAppendPostBlockEmptyLineRequested = false;
- }
- }
- }
- /**
- * Append a closing header to the previous closing brace, if possible
- */
- void ASFormatter::appendClosingHeader()
- {
- // if a blank line does not precede this
- // or last line is not a one line block, attach header
- bool previousLineIsEmpty = isEmptyLine(formattedLine);
- int previousLineIsOneLineBlock = 0;
- size_t firstBrace = findNextChar(formattedLine, '{');
- if (firstBrace != string::npos)
- previousLineIsOneLineBlock = isOneLineBlockReached(formattedLine, firstBrace);
- if (!previousLineIsEmpty
- && previousLineIsOneLineBlock == 0)
- {
- isInLineBreak = false;
- appendSpacePad();
- spacePadNum = 0; // don't count as comment padding
- }
- }
- /**
- * Add braces to a single line statement following a header.
- * braces are not added if the proper conditions are not met.
- * braces are added to the currentLine.
- */
- bool ASFormatter::addBracesToStatement()
- {
- assert(isImmediatelyPostHeader);
- if (currentHeader != &AS_IF
- && currentHeader != &AS_ELSE
- && currentHeader != &AS_FOR
- && currentHeader != &AS_WHILE
- && currentHeader != &AS_DO
- && currentHeader != &AS_FOREACH
- && currentHeader != &AS_QFOREACH
- && currentHeader != &AS_QFOREVER
- && currentHeader != &AS_FOREVER)
- return false;
- if (currentHeader == &AS_WHILE && foundClosingHeader) // do-while
- return false;
- // do not brace an empty statement
- if (currentChar == ';')
- return false;
- // do not add if a header follows
- if (isCharPotentialHeader(currentLine, charNum))
- if (findHeader(headers) != nullptr)
- return false;
- // find the next semi-colon
- size_t nextSemiColon = charNum;
- if (currentChar != ';')
- nextSemiColon = findNextChar(currentLine, ';', charNum + 1);
- if (nextSemiColon == string::npos)
- return false;
- // add closing brace before changing the line length
- if (nextSemiColon == currentLine.length() - 1)
- currentLine.append(" }");
- else
- currentLine.insert(nextSemiColon + 1, " }");
- // add opening brace
- currentLine.insert(charNum, "{ ");
- assert(computeChecksumIn("{}"));
- currentChar = '{';
- if ((int) currentLine.find_first_not_of(" \t") == charNum)
- currentLineBeginsWithBrace = true;
- // remove extra spaces
- if (!shouldAddOneLineBraces)
- {
- size_t lastText = formattedLine.find_last_not_of(" \t");
- if ((formattedLine.length() - 1) - lastText > 1)
- formattedLine.erase(lastText + 1);
- }
- return true;
- }
- /**
- * Remove braces from a single line statement following a header.
- * braces are not removed if the proper conditions are not met.
- * The first brace is replaced by a space.
- */
- bool ASFormatter::removeBracesFromStatement()
- {
- assert(isImmediatelyPostHeader);
- assert(currentChar == '{');
- if (currentHeader != &AS_IF
- && currentHeader != &AS_ELSE
- && currentHeader != &AS_FOR
- && currentHeader != &AS_WHILE
- && currentHeader != &AS_FOREACH)
- return false;
- if (currentHeader == &AS_WHILE && foundClosingHeader) // do-while
- return false;
- bool isFirstLine = true;
- string nextLine_;
- // leave nextLine_ empty if end of line comment follows
- if (!isBeforeAnyLineEndComment(charNum) || currentLineBeginsWithBrace)
- nextLine_ = currentLine.substr(charNum + 1);
- size_t nextChar = 0;
- // find the first non-blank text
- ASPeekStream stream(sourceIterator);
- while (stream.hasMoreLines() || isFirstLine)
- {
- if (isFirstLine)
- isFirstLine = false;
- else
- {
- nextLine_ = stream.peekNextLine();
- nextChar = 0;
- }
- nextChar = nextLine_.find_first_not_of(" \t", nextChar);
- if (nextChar != string::npos)
- break;
- }
- // don't remove if comments or a header follow the brace
- if ((nextLine_.compare(nextChar, 2, "/*") == 0)
- || (nextLine_.compare(nextChar, 2, "//") == 0)
- || (isCharPotentialHeader(nextLine_, nextChar)
- && ASBase::findHeader(nextLine_, nextChar, headers) != nullptr))
- return false;
- // find the next semi-colon
- size_t nextSemiColon = nextChar;
- if (nextLine_[nextChar] != ';')
- nextSemiColon = findNextChar(nextLine_, ';', nextChar + 1);
- if (nextSemiColon == string::npos)
- return false;
- // find the closing brace
- isFirstLine = true;
- nextChar = nextSemiColon + 1;
- while (stream.hasMoreLines() || isFirstLine)
- {
- if (isFirstLine)
- isFirstLine = false;
- else
- {
- nextLine_ = stream.peekNextLine();
- nextChar = 0;
- }
- nextChar = nextLine_.find_first_not_of(" \t", nextChar);
- if (nextChar != string::npos)
- break;
- }
- if (nextLine_.length() == 0 || nextLine_[nextChar] != '}')
- return false;
- // remove opening brace
- currentLine[charNum] = currentChar = ' ';
- assert(adjustChecksumIn(-'{'));
- return true;
- }
- /**
- * Find the next character that is not in quotes or a comment.
- *
- * @param line the line to be searched.
- * @param searchChar the char to find.
- * @param searchStart the start position on the line (default is 0).
- * @return the position on the line or string::npos if not found.
- */
- size_t ASFormatter::findNextChar(const string& line, char searchChar, int searchStart /*0*/) const
- {
- // find the next searchChar
- size_t i;
- for (i = searchStart; i < line.length(); i++)
- {
- if (line.compare(i, 2, "//") == 0)
- return string::npos;
- if (line.compare(i, 2, "/*") == 0)
- {
- size_t endComment = line.find("*/", i + 2);
- if (endComment == string::npos)
- return string::npos;
- i = endComment + 2;
- if (i >= line.length())
- return string::npos;
- }
- if (line[i] == '"'
- || (line[i] == '\'' && !isDigitSeparator(line, i)))
- {
- char quote = line[i];
- while (i < line.length())
- {
- size_t endQuote = line.find(quote, i + 1);
- if (endQuote == string::npos)
- return string::npos;
- i = endQuote;
- if (line[endQuote - 1] != '\\') // check for '\"'
- break;
- if (line[endQuote - 2] == '\\') // check for '\\'
- break;
- }
- }
- if (line[i] == searchChar)
- break;
- // for now don't process C# 'delegate' braces
- // do this last in case the search char is a '{'
- if (line[i] == '{')
- return string::npos;
- }
- if (i >= line.length()) // didn't find searchChar
- return string::npos;
- return i;
- }
- /**
- * Look ahead in the file to see if a struct has access modifiers.
- *
- * @param firstLine a reference to the line to indent.
- * @param index the current line index.
- * @return true if the struct has access modifiers.
- */
- bool ASFormatter::isStructAccessModified(const string& firstLine, size_t index) const
- {
- assert(firstLine[index] == '{');
- assert(isCStyle());
- bool isFirstLine = true;
- size_t braceCount = 1;
- string nextLine_ = firstLine.substr(index + 1);
- ASPeekStream stream(sourceIterator);
- // find the first non-blank text, bypassing all comments and quotes.
- bool isInComment_ = false;
- bool isInQuote_ = false;
- char quoteChar_ = ' ';
- while (stream.hasMoreLines() || isFirstLine)
- {
- if (isFirstLine)
- isFirstLine = false;
- else
- nextLine_ = stream.peekNextLine();
- // parse the line
- for (size_t i = 0; i < nextLine_.length(); i++)
- {
- if (isWhiteSpace(nextLine_[i]))
- continue;
- if (nextLine_.compare(i, 2, "/*") == 0)
- isInComment_ = true;
- if (isInComment_)
- {
- if (nextLine_.compare(i, 2, "*/") == 0)
- {
- isInComment_ = false;
- ++i;
- }
- continue;
- }
- if (nextLine_[i] == '\\')
- {
- ++i;
- continue;
- }
- if (isInQuote_)
- {
- if (nextLine_[i] == quoteChar_)
- isInQuote_ = false;
- continue;
- }
- if (nextLine_[i] == '"'
- || (nextLine_[i] == '\'' && !isDigitSeparator(nextLine_, i)))
- {
- isInQuote_ = true;
- quoteChar_ = nextLine_[i];
- continue;
- }
- if (nextLine_.compare(i, 2, "//") == 0)
- {
- i = nextLine_.length();
- continue;
- }
- // handle braces
- if (nextLine_[i] == '{')
- ++braceCount;
- if (nextLine_[i] == '}')
- --braceCount;
- if (braceCount == 0)
- return false;
- // check for access modifiers
- if (isCharPotentialHeader(nextLine_, i))
- {
- if (findKeyword(nextLine_, i, AS_PUBLIC)
- || findKeyword(nextLine_, i, AS_PRIVATE)
- || findKeyword(nextLine_, i, AS_PROTECTED))
- return true;
- string name = getCurrentWord(nextLine_, i);
- i += name.length() - 1;
- }
- } // end of for loop
- } // end of while loop
- return false;
- }
- /**
- * Look ahead in the file to see if a preprocessor block is indentable.
- *
- * @param firstLine a reference to the line to indent.
- * @param index the current line index.
- * @return true if the block is indentable.
- */
- bool ASFormatter::isIndentablePreprocessorBlock(const string& firstLine, size_t index)
- {
- assert(firstLine[index] == '#');
- bool isFirstLine = true;
- bool isInIndentableBlock = false;
- bool blockContainsBraces = false;
- bool blockContainsDefineContinuation = false;
- bool isInClassConstructor = false;
- bool isPotentialHeaderGuard = false; // ifndef is first preproc statement
- bool isPotentialHeaderGuard2 = false; // define is within the first proproc
- int numBlockIndents = 0;
- int lineParenCount = 0;
- string nextLine_ = firstLine.substr(index);
- auto stream = make_shared<ASPeekStream>(sourceIterator);
- // find end of the block, bypassing all comments and quotes.
- bool isInComment_ = false;
- bool isInQuote_ = false;
- char quoteChar_ = ' ';
- while (stream->hasMoreLines() || isFirstLine)
- {
- if (isFirstLine)
- isFirstLine = false;
- else
- nextLine_ = stream->peekNextLine();
- // parse the line
- for (size_t i = 0; i < nextLine_.length(); i++)
- {
- if (isWhiteSpace(nextLine_[i]))
- continue;
- if (nextLine_.compare(i, 2, "/*") == 0)
- isInComment_ = true;
- if (isInComment_)
- {
- if (nextLine_.compare(i, 2, "*/") == 0)
- {
- isInComment_ = false;
- ++i;
- }
- continue;
- }
- if (nextLine_[i] == '\\')
- {
- ++i;
- continue;
- }
- if (isInQuote_)
- {
- if (nextLine_[i] == quoteChar_)
- isInQuote_ = false;
- continue;
- }
- if (nextLine_[i] == '"'
- || (nextLine_[i] == '\'' && !isDigitSeparator(nextLine_, i)))
- {
- isInQuote_ = true;
- quoteChar_ = nextLine_[i];
- continue;
- }
- if (nextLine_.compare(i, 2, "//") == 0)
- {
- i = nextLine_.length();
- continue;
- }
- // handle preprocessor statement
- if (nextLine_[i] == '#')
- {
- string preproc = ASBeautifier::extractPreprocessorStatement(nextLine_);
- if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") // #if, #ifdef, #ifndef
- {
- numBlockIndents += 1;
- isInIndentableBlock = true;
- // flag first preprocessor conditional for header include guard check
- if (!processedFirstConditional)
- {
- processedFirstConditional = true;
- isFirstPreprocConditional = true;
- if (isNDefPreprocStatement(nextLine_, preproc))
- isPotentialHeaderGuard = true;
- }
- }
- else if (preproc == "endif")
- {
- if (numBlockIndents > 0)
- numBlockIndents -= 1;
- // must exit BOTH loops
- if (numBlockIndents == 0)
- goto EndOfWhileLoop;
- }
- else if (preproc == "define")
- {
- if (nextLine_[nextLine_.length() - 1] == '\\')
- blockContainsDefineContinuation = true;
- // check for potential header include guards
- else if (isPotentialHeaderGuard && numBlockIndents == 1)
- isPotentialHeaderGuard2 = true;
- }
- i = nextLine_.length();
- continue;
- }
- // handle exceptions
- if (nextLine_[i] == '{' || nextLine_[i] == '}')
- blockContainsBraces = true;
- else if (nextLine_[i] == '(')
- ++lineParenCount;
- else if (nextLine_[i] == ')')
- --lineParenCount;
- else if (nextLine_[i] == ':')
- {
- // check for '::'
- if (nextLine_.length() > i && nextLine_[i + 1] == ':')
- ++i;
- else
- isInClassConstructor = true;
- }
- // bypass unnecessary parsing - must exit BOTH loops
- if (blockContainsBraces || isInClassConstructor || blockContainsDefineContinuation)
- goto EndOfWhileLoop;
- } // end of for loop, end of line
- if (lineParenCount != 0)
- break;
- } // end of while loop
- EndOfWhileLoop:
- preprocBlockEnd = sourceIterator->tellg();
- if (preprocBlockEnd < 0)
- preprocBlockEnd = sourceIterator->getStreamLength();
- if (blockContainsBraces
- || isInClassConstructor
- || blockContainsDefineContinuation
- || lineParenCount != 0
- || numBlockIndents != 0)
- isInIndentableBlock = false;
- // find next executable instruction
- // this WILL RESET the get pointer
- string nextText = peekNextText("", false, stream);
- // bypass header include guards
- if (isFirstPreprocConditional)
- {
- isFirstPreprocConditional = false;
- if (nextText.empty() && isPotentialHeaderGuard2)
- {
- isInIndentableBlock = false;
- preprocBlockEnd = 0;
- }
- }
- // this allows preprocessor blocks within this block to be indented
- if (!isInIndentableBlock)
- preprocBlockEnd = 0;
- // peekReset() is done by previous peekNextText()
- return isInIndentableBlock;
- }
- bool ASFormatter::isNDefPreprocStatement(const string& nextLine_, const string& preproc) const
- {
- if (preproc == "ifndef")
- return true;
- // check for '!defined'
- if (preproc == "if")
- {
- size_t i = nextLine_.find('!');
- if (i == string::npos)
- return false;
- i = nextLine_.find_first_not_of(" \t", ++i);
- if (i != string::npos && nextLine_.compare(i, 7, "defined") == 0)
- return true;
- }
- return false;
- }
- /**
- * Check to see if this is an EXEC SQL statement.
- *
- * @param line a reference to the line to indent.
- * @param index the current line index.
- * @return true if the statement is EXEC SQL.
- */
- bool ASFormatter::isExecSQL(const string& line, size_t index) const
- {
- if (line[index] != 'e' && line[index] != 'E') // quick check to reject most
- return false;
- string word;
- if (isCharPotentialHeader(line, index))
- word = getCurrentWord(line, index);
- for (size_t i = 0; i < word.length(); i++)
- word[i] = (char) toupper(word[i]);
- if (word != "EXEC")
- return false;
- size_t index2 = index + word.length();
- index2 = line.find_first_not_of(" \t", index2);
- if (index2 == string::npos)
- return false;
- word.erase();
- if (isCharPotentialHeader(line, index2))
- word = getCurrentWord(line, index2);
- for (size_t i = 0; i < word.length(); i++)
- word[i] = (char) toupper(word[i]);
- if (word != "SQL")
- return false;
- return true;
- }
- /**
- * The continuation lines must be adjusted so the leading spaces
- * is equivalent to the text on the opening line.
- *
- * Updates currentLine and charNum.
- */
- void ASFormatter::trimContinuationLine()
- {
- size_t len = currentLine.length();
- size_t tabSize = getTabLength();
- charNum = 0;
- if (leadingSpaces > 0 && len > 0)
- {
- size_t i;
- size_t continuationIncrementIn = 0;
- for (i = 0; (i < len) && (i + continuationIncrementIn < leadingSpaces); i++)
- {
- if (!isWhiteSpace(currentLine[i])) // don't delete any text
- {
- if (i < continuationIncrementIn)
- leadingSpaces = i + tabIncrementIn;
- continuationIncrementIn = tabIncrementIn;
- break;
- }
- if (currentLine[i] == '\t')
- continuationIncrementIn += tabSize - 1 - ((continuationIncrementIn + i) % tabSize);
- }
- if ((int) continuationIncrementIn == tabIncrementIn)
- charNum = i;
- else
- {
- // build a new line with the equivalent leading chars
- string newLine;
- int leadingChars = 0;
- if ((int) leadingSpaces > tabIncrementIn)
- leadingChars = leadingSpaces - tabIncrementIn;
- newLine.append(leadingChars, ' ');
- newLine.append(currentLine, i, len - i);
- currentLine = newLine;
- charNum = leadingChars;
- if (currentLine.length() == 0)
- currentLine = string(" "); // a null is inserted if this is not done
- }
- if (i >= len)
- charNum = 0;
- }
- }
- /**
- * Determine if a header is a closing header
- *
- * @return true if the header is a closing header.
- */
- bool ASFormatter::isClosingHeader(const string* header) const
- {
- return (header == &AS_ELSE
- || header == &AS_CATCH
- || header == &AS_FINALLY);
- }
- /**
- * Determine if a * following a closing paren is immediately.
- * after a cast. If so it is a deference and not a multiply.
- * e.g. "(int*) *ptr" is a deference.
- */
- bool ASFormatter::isImmediatelyPostCast() const
- {
- assert(previousNonWSChar == ')' && currentChar == '*');
- // find preceding closing paren on currentLine or readyFormattedLine
- string line; // currentLine or readyFormattedLine
- size_t paren = currentLine.rfind(')', charNum);
- if (paren != string::npos)
- line = currentLine;
- // if not on currentLine it must be on the previous line
- else
- {
- line = readyFormattedLine;
- paren = line.rfind(')');
- if (paren == string::npos)
- return false;
- }
- if (paren == 0)
- return false;
- // find character preceding the closing paren
- size_t lastChar = line.find_last_not_of(" \t", paren - 1);
- if (lastChar == string::npos)
- return false;
- // check for pointer cast
- if (line[lastChar] == '*')
- return true;
- return false;
- }
- /**
- * Determine if a < is a template definition or instantiation.
- * Sets the class variables isInTemplate and templateDepth.
- */
- void ASFormatter::checkIfTemplateOpener()
- {
- assert(!isInTemplate && currentChar == '<');
- // find first char after the '<' operators
- size_t firstChar = currentLine.find_first_not_of("< \t", charNum);
- if (firstChar == string::npos
- || currentLine[firstChar] == '=')
- {
- // this is not a template -> leave...
- isInTemplate = false;
- return;
- }
- bool isFirstLine = true;
- int parenDepth_ = 0;
- int maxTemplateDepth = 0;
- templateDepth = 0;
- string nextLine_ = currentLine.substr(charNum);
- ASPeekStream stream(sourceIterator);
- // find the angle braces, bypassing all comments and quotes.
- bool isInComment_ = false;
- bool isInQuote_ = false;
- char quoteChar_ = ' ';
- while (stream.hasMoreLines() || isFirstLine)
- {
- if (isFirstLine)
- isFirstLine = false;
- else
- nextLine_ = stream.peekNextLine();
- // parse the line
- for (size_t i = 0; i < nextLine_.length(); i++)
- {
- char currentChar_ = nextLine_[i];
- if (isWhiteSpace(currentChar_))
- continue;
- if (nextLine_.compare(i, 2, "/*") == 0)
- isInComment_ = true;
- if (isInComment_)
- {
- if (nextLine_.compare(i, 2, "*/") == 0)
- {
- isInComment_ = false;
- ++i;
- }
- continue;
- }
- if (currentChar_ == '\\')
- {
- ++i;
- continue;
- }
- if (isInQuote_)
- {
- if (currentChar_ == quoteChar_)
- isInQuote_ = false;
- continue;
- }
- if (currentChar_ == '"'
- || (currentChar_ == '\'' && !isDigitSeparator(nextLine_, i)))
- {
- isInQuote_ = true;
- quoteChar_ = currentChar_;
- continue;
- }
- if (nextLine_.compare(i, 2, "//") == 0)
- {
- i = nextLine_.length();
- continue;
- }
- // not in a comment or quote
- if (currentChar_ == '<')
- {
- ++templateDepth;
- ++maxTemplateDepth;
- continue;
- }
- else if (currentChar_ == '>')
- {
- --templateDepth;
- if (templateDepth == 0)
- {
- if (parenDepth_ == 0)
- {
- // this is a template!
- isInTemplate = true;
- templateDepth = maxTemplateDepth;
- }
- return;
- }
- continue;
- }
- else if (currentChar_ == '(' || currentChar_ == ')')
- {
- if (currentChar_ == '(')
- ++parenDepth_;
- else
- --parenDepth_;
- if (parenDepth_ >= 0)
- continue;
- // this is not a template -> leave...
- isInTemplate = false;
- templateDepth = 0;
- return;
- }
- else if (nextLine_.compare(i, 2, AS_AND) == 0
- || nextLine_.compare(i, 2, AS_OR) == 0)
- {
- // this is not a template -> leave...
- isInTemplate = false;
- templateDepth = 0;
- return;
- }
- else if (currentChar_ == ',' // comma, e.g. A<int, char>
- || currentChar_ == '&' // reference, e.g. A<int&>
- || currentChar_ == '*' // pointer, e.g. A<int*>
- || currentChar_ == '^' // C++/CLI managed pointer, e.g. A<int^>
- || currentChar_ == ':' // ::, e.g. std::string
- || currentChar_ == '=' // assign e.g. default parameter
- || currentChar_ == '[' // [] e.g. string[]
- || currentChar_ == ']' // [] e.g. string[]
- || currentChar_ == '(' // (...) e.g. function definition
- || currentChar_ == ')' // (...) e.g. function definition
- || (isJavaStyle() && currentChar_ == '?') // Java wildcard
- )
- {
- continue;
- }
- else if (!isLegalNameChar(currentChar_))
- {
- // this is not a template -> leave...
- isInTemplate = false;
- templateDepth = 0;
- return;
- }
- string name = getCurrentWord(nextLine_, i);
- i += name.length() - 1;
- } // end for loop
- } // end while loop
- }
- void ASFormatter::updateFormattedLineSplitPoints(char appendedChar)
- {
- assert(maxCodeLength != string::npos);
- assert(formattedLine.length() > 0);
- if (!isOkToSplitFormattedLine())
- return;
- char nextChar = peekNextChar();
- // don't split before an end of line comment
- if (nextChar == '/')
- return;
- // don't split before or after a brace
- if (appendedChar == '{' || appendedChar == '}'
- || previousNonWSChar == '{' || previousNonWSChar == '}'
- || nextChar == '{' || nextChar == '}'
- || currentChar == '{' || currentChar == '}') // currentChar tests for an appended brace
- return;
- // don't split before or after a block paren
- if (appendedChar == '[' || appendedChar == ']'
- || previousNonWSChar == '['
- || nextChar == '[' || nextChar == ']')
- return;
- if (isWhiteSpace(appendedChar))
- {
- if (nextChar != ')' // space before a closing paren
- && nextChar != '(' // space before an opening paren
- && nextChar != '/' // space before a comment
- && nextChar != ':' // space before a colon
- && currentChar != ')' // appended space before and after a closing paren
- && currentChar != '(' // appended space before and after a opening paren
- && previousNonWSChar != '(' // decided at the '('
- // don't break before a pointer or reference aligned to type
- && !(nextChar == '*'
- && !isCharPotentialOperator(previousNonWSChar)
- && pointerAlignment == PTR_ALIGN_TYPE)
- && !(nextChar == '&'
- && !isCharPotentialOperator(previousNonWSChar)
- && (referenceAlignment == REF_ALIGN_TYPE
- || (referenceAlignment == REF_SAME_AS_PTR && pointerAlignment == PTR_ALIGN_TYPE)))
- )
- {
- if (formattedLine.length() - 1 <= maxCodeLength)
- maxWhiteSpace = formattedLine.length() - 1;
- else
- maxWhiteSpacePending = formattedLine.length() - 1;
- }
- }
- // unpadded closing parens may split after the paren (counts as whitespace)
- else if (appendedChar == ')')
- {
- if (nextChar != ')'
- && nextChar != ' '
- && nextChar != ';'
- && nextChar != ','
- && nextChar != '.'
- && !(nextChar == '-' && pointerSymbolFollows())) // check for ->
- {
- if (formattedLine.length() <= maxCodeLength)
- maxWhiteSpace = formattedLine.length();
- else
- maxWhiteSpacePending = formattedLine.length();
- }
- }
- // unpadded commas may split after the comma
- else if (appendedChar == ',')
- {
- if (formattedLine.length() <= maxCodeLength)
- maxComma = formattedLine.length();
- else
- maxCommaPending = formattedLine.length();
- }
- else if (appendedChar == '(')
- {
- if (nextChar != ')' && nextChar != '(' && nextChar != '"' && nextChar != '\'')
- {
- // if follows an operator break before
- size_t parenNum;
- if (isCharPotentialOperator(previousNonWSChar))
- parenNum = formattedLine.length() - 1;
- else
- parenNum = formattedLine.length();
- if (formattedLine.length() <= maxCodeLength)
- maxParen = parenNum;
- else
- maxParenPending = parenNum;
- }
- }
- else if (appendedChar == ';')
- {
- if (nextChar != ' ' && nextChar != '}' && nextChar != '/') // check for following comment
- {
- if (formattedLine.length() <= maxCodeLength)
- maxSemi = formattedLine.length();
- else
- maxSemiPending = formattedLine.length();
- }
- }
- }
- void ASFormatter::updateFormattedLineSplitPointsOperator(const string& sequence)
- {
- assert(maxCodeLength != string::npos);
- assert(formattedLine.length() > 0);
- if (!isOkToSplitFormattedLine())
- return;
- char nextChar = peekNextChar();
- // don't split before an end of line comment
- if (nextChar == '/')
- return;
- // check for logical conditional
- if (sequence == "||" || sequence == "&&" || sequence == "or" || sequence == "and")
- {
- if (shouldBreakLineAfterLogical)
- {
- if (formattedLine.length() <= maxCodeLength)
- maxAndOr = formattedLine.length();
- else
- maxAndOrPending = formattedLine.length();
- }
- else
- {
- // adjust for leading space in the sequence
- size_t sequenceLength = sequence.length();
- if (formattedLine.length() > sequenceLength
- && isWhiteSpace(formattedLine[formattedLine.length() - sequenceLength - 1]))
- sequenceLength++;
- if (formattedLine.length() - sequenceLength <= maxCodeLength)
- maxAndOr = formattedLine.length() - sequenceLength;
- else
- maxAndOrPending = formattedLine.length() - sequenceLength;
- }
- }
- // comparison operators will split after the operator (counts as whitespace)
- else if (sequence == "==" || sequence == "!=" || sequence == ">=" || sequence == "<=")
- {
- if (formattedLine.length() <= maxCodeLength)
- maxWhiteSpace = formattedLine.length();
- else
- maxWhiteSpacePending = formattedLine.length();
- }
- // unpadded operators that will split BEFORE the operator (counts as whitespace)
- else if (sequence == "+" || sequence == "-" || sequence == "?")
- {
- if (charNum > 0
- && !(sequence == "+" && isInExponent())
- && !(sequence == "-" && isInExponent())
- && (isLegalNameChar(currentLine[charNum - 1])
- || currentLine[charNum - 1] == ')'
- || currentLine[charNum - 1] == ']'
- || currentLine[charNum - 1] == '\"'))
- {
- if (formattedLine.length() - 1 <= maxCodeLength)
- maxWhiteSpace = formattedLine.length() - 1;
- else
- maxWhiteSpacePending = formattedLine.length() - 1;
- }
- }
- // unpadded operators that will USUALLY split AFTER the operator (counts as whitespace)
- else if (sequence == "=" || sequence == ":")
- {
- // split BEFORE if the line is too long
- // do NOT use <= here, must allow for a brace attached to an array
- size_t splitPoint = 0;
- if (formattedLine.length() < maxCodeLength)
- splitPoint = formattedLine.length();
- else
- splitPoint = formattedLine.length() - 1;
- // padded or unpadded arrays
- if (previousNonWSChar == ']')
- {
- if (formattedLine.length() - 1 <= maxCodeLength)
- maxWhiteSpace = splitPoint;
- else
- maxWhiteSpacePending = splitPoint;
- }
- else if (charNum > 0
- && (isLegalNameChar(currentLine[charNum - 1])
- || currentLine[charNum - 1] == ')'
- || currentLine[charNum - 1] == ']'))
- {
- if (formattedLine.length() <= maxCodeLength)
- maxWhiteSpace = splitPoint;
- else
- maxWhiteSpacePending = splitPoint;
- }
- }
- }
- /**
- * Update the split point when a pointer or reference is formatted.
- * The argument is the maximum index of the last whitespace character.
- */
- void ASFormatter::updateFormattedLineSplitPointsPointerOrReference(size_t index)
- {
- assert(maxCodeLength != string::npos);
- assert(formattedLine.length() > 0);
- assert(index < formattedLine.length());
- if (!isOkToSplitFormattedLine())
- return;
- if (index < maxWhiteSpace) // just in case
- return;
- if (index <= maxCodeLength)
- maxWhiteSpace = index;
- else
- maxWhiteSpacePending = index;
- }
- bool ASFormatter::isOkToSplitFormattedLine()
- {
- assert(maxCodeLength != string::npos);
- // Is it OK to split the line?
- if (shouldKeepLineUnbroken
- || isInLineComment
- || isInComment
- || isInQuote
- || isInCase
- || isInPreprocessor
- || isInExecSQL
- || isInAsm || isInAsmOneLine || isInAsmBlock
- || isInTemplate)
- return false;
- if (!isOkToBreakBlock(braceTypeStack->back()) && currentChar != '{')
- {
- shouldKeepLineUnbroken = true;
- clearFormattedLineSplitPoints();
- return false;
- }
- if (isBraceType(braceTypeStack->back(), ARRAY_TYPE))
- {
- shouldKeepLineUnbroken = true;
- if (!isBraceType(braceTypeStack->back(), ARRAY_NIS_TYPE))
- clearFormattedLineSplitPoints();
- return false;
- }
- return true;
- }
- /* This is called if the option maxCodeLength is set.
- */
- void ASFormatter::testForTimeToSplitFormattedLine()
- {
- // DO NOT ASSERT maxCodeLength HERE
- // should the line be split
- if (formattedLine.length() > maxCodeLength && !isLineReady)
- {
- size_t splitPoint = findFormattedLineSplitPoint();
- if (splitPoint > 0 && splitPoint < formattedLine.length())
- {
- string splitLine = formattedLine.substr(splitPoint);
- formattedLine = formattedLine.substr(0, splitPoint);
- breakLine(true);
- formattedLine = splitLine;
- // if break-blocks is requested and this is a one-line statement
- string nextWord = ASBeautifier::getNextWord(currentLine, charNum - 1);
- if (isAppendPostBlockEmptyLineRequested
- && (nextWord == "break" || nextWord == "continue"))
- {
- isAppendPostBlockEmptyLineRequested = false;
- isPrependPostBlockEmptyLineRequested = true;
- }
- else
- isPrependPostBlockEmptyLineRequested = false;
- // adjust max split points
- maxAndOr = (maxAndOr > splitPoint) ? (maxAndOr - splitPoint) : 0;
- maxSemi = (maxSemi > splitPoint) ? (maxSemi - splitPoint) : 0;
- maxComma = (maxComma > splitPoint) ? (maxComma - splitPoint) : 0;
- maxParen = (maxParen > splitPoint) ? (maxParen - splitPoint) : 0;
- maxWhiteSpace = (maxWhiteSpace > splitPoint) ? (maxWhiteSpace - splitPoint) : 0;
- if (maxSemiPending > 0)
- {
- maxSemi = (maxSemiPending > splitPoint) ? (maxSemiPending - splitPoint) : 0;
- maxSemiPending = 0;
- }
- if (maxAndOrPending > 0)
- {
- maxAndOr = (maxAndOrPending > splitPoint) ? (maxAndOrPending - splitPoint) : 0;
- maxAndOrPending = 0;
- }
- if (maxCommaPending > 0)
- {
- maxComma = (maxCommaPending > splitPoint) ? (maxCommaPending - splitPoint) : 0;
- maxCommaPending = 0;
- }
- if (maxParenPending > 0)
- {
- maxParen = (maxParenPending > splitPoint) ? (maxParenPending - splitPoint) : 0;
- maxParenPending = 0;
- }
- if (maxWhiteSpacePending > 0)
- {
- maxWhiteSpace = (maxWhiteSpacePending > splitPoint) ? (maxWhiteSpacePending - splitPoint) : 0;
- maxWhiteSpacePending = 0;
- }
- // don't allow an empty formatted line
- size_t firstText = formattedLine.find_first_not_of(" \t");
- if (firstText == string::npos && formattedLine.length() > 0)
- {
- formattedLine.erase();
- clearFormattedLineSplitPoints();
- if (isWhiteSpace(currentChar))
- for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++)
- goForward(1);
- }
- else if (firstText > 0)
- {
- formattedLine.erase(0, firstText);
- maxSemi = (maxSemi > firstText) ? (maxSemi - firstText) : 0;
- maxAndOr = (maxAndOr > firstText) ? (maxAndOr - firstText) : 0;
- maxComma = (maxComma > firstText) ? (maxComma - firstText) : 0;
- maxParen = (maxParen > firstText) ? (maxParen - firstText) : 0;
- maxWhiteSpace = (maxWhiteSpace > firstText) ? (maxWhiteSpace - firstText) : 0;
- }
- // reset formattedLineCommentNum
- if (formattedLineCommentNum != string::npos)
- {
- formattedLineCommentNum = formattedLine.find("//");
- if (formattedLineCommentNum == string::npos)
- formattedLineCommentNum = formattedLine.find("/*");
- }
- }
- }
- }
- size_t ASFormatter::findFormattedLineSplitPoint() const
- {
- assert(maxCodeLength != string::npos);
- // determine where to split
- size_t minCodeLength = 10;
- size_t splitPoint = 0;
- splitPoint = maxSemi;
- if (maxAndOr >= minCodeLength)
- splitPoint = maxAndOr;
- if (splitPoint < minCodeLength)
- {
- splitPoint = maxWhiteSpace;
- // use maxParen instead if it is long enough
- if (maxParen > splitPoint
- || maxParen >= maxCodeLength * .7)
- splitPoint = maxParen;
- // use maxComma instead if it is long enough
- // increasing the multiplier causes more splits at whitespace
- if (maxComma > splitPoint
- || maxComma >= maxCodeLength * .3)
- splitPoint = maxComma;
- }
- // replace split point with first available break point
- if (splitPoint < minCodeLength)
- {
- splitPoint = string::npos;
- if (maxSemiPending > 0 && maxSemiPending < splitPoint)
- splitPoint = maxSemiPending;
- if (maxAndOrPending > 0 && maxAndOrPending < splitPoint)
- splitPoint = maxAndOrPending;
- if (maxCommaPending > 0 && maxCommaPending < splitPoint)
- splitPoint = maxCommaPending;
- if (maxParenPending > 0 && maxParenPending < splitPoint)
- splitPoint = maxParenPending;
- if (maxWhiteSpacePending > 0 && maxWhiteSpacePending < splitPoint)
- splitPoint = maxWhiteSpacePending;
- if (splitPoint == string::npos)
- splitPoint = 0;
- }
- // if remaining line after split is too long
- else if (formattedLine.length() - splitPoint > maxCodeLength)
- {
- // if end of the currentLine, find a new split point
- size_t newCharNum;
- if (isCharPotentialHeader(currentLine, charNum))
- newCharNum = getCurrentWord(currentLine, charNum).length() + charNum;
- else
- newCharNum = charNum + 2;
- if (newCharNum + 1 > currentLine.length())
- {
- // don't move splitPoint from before a conditional to after
- if (maxWhiteSpace > splitPoint + 3)
- splitPoint = maxWhiteSpace;
- if (maxParen > splitPoint)
- splitPoint = maxParen;
- }
- }
- return splitPoint;
- }
- void ASFormatter::clearFormattedLineSplitPoints()
- {
- maxSemi = 0;
- maxAndOr = 0;
- maxComma = 0;
- maxParen = 0;
- maxWhiteSpace = 0;
- maxSemiPending = 0;
- maxAndOrPending = 0;
- maxCommaPending = 0;
- maxParenPending = 0;
- maxWhiteSpacePending = 0;
- }
- /**
- * Check if a pointer symbol (->) follows on the currentLine.
- */
- bool ASFormatter::pointerSymbolFollows() const
- {
- size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
- if (peekNum == string::npos || currentLine.compare(peekNum, 2, "->") != 0)
- return false;
- return true;
- }
- /**
- * Compute the input checksum.
- * This is called as an assert so it for is debug config only
- */
- bool ASFormatter::computeChecksumIn(const string& currentLine_)
- {
- for (size_t i = 0; i < currentLine_.length(); i++)
- if (!isWhiteSpace(currentLine_[i]))
- checksumIn += currentLine_[i];
- return true;
- }
- /**
- * Adjust the input checksum for deleted chars.
- * This is called as an assert so it for is debug config only
- */
- bool ASFormatter::adjustChecksumIn(int adjustment)
- {
- checksumIn += adjustment;
- return true;
- }
- /**
- * get the value of checksumIn for unit testing
- *
- * @return checksumIn.
- */
- size_t ASFormatter::getChecksumIn() const
- {
- return checksumIn;
- }
- /**
- * Compute the output checksum.
- * This is called as an assert so it is for debug config only
- */
- bool ASFormatter::computeChecksumOut(const string& beautifiedLine)
- {
- for (size_t i = 0; i < beautifiedLine.length(); i++)
- if (!isWhiteSpace(beautifiedLine[i]))
- checksumOut += beautifiedLine[i];
- return true;
- }
- /**
- * Return isLineReady for the final check at end of file.
- */
- bool ASFormatter::getIsLineReady() const
- {
- return isLineReady;
- }
- /**
- * get the value of checksumOut for unit testing
- *
- * @return checksumOut.
- */
- size_t ASFormatter::getChecksumOut() const
- {
- return checksumOut;
- }
- /**
- * Return the difference in checksums.
- * If zero all is okay.
- */
- int ASFormatter::getChecksumDiff() const
- {
- return checksumOut - checksumIn;
- }
- // for unit testing
- int ASFormatter::getFormatterFileType() const
- {
- return formatterFileType;
- }
- // Check if an operator follows the next word.
- // The next word must be a legal name.
- const string* ASFormatter::getFollowingOperator() const
- {
- // find next word
- size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1);
- if (nextNum == string::npos)
- return nullptr;
- if (!isLegalNameChar(currentLine[nextNum]))
- return nullptr;
- // bypass next word and following spaces
- while (nextNum < currentLine.length())
- {
- if (!isLegalNameChar(currentLine[nextNum])
- && !isWhiteSpace(currentLine[nextNum]))
- break;
- nextNum++;
- }
- if (nextNum >= currentLine.length()
- || !isCharPotentialOperator(currentLine[nextNum])
- || currentLine[nextNum] == '/') // comment
- return nullptr;
- const string* newOperator = ASBase::findOperator(currentLine, nextNum, operators);
- return newOperator;
- }
- // Check following data to determine if the current character is an array operator.
- bool ASFormatter::isArrayOperator() const
- {
- assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
- assert(isBraceType(braceTypeStack->back(), ARRAY_TYPE));
- // find next word
- size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1);
- if (nextNum == string::npos)
- return false;
- if (!isLegalNameChar(currentLine[nextNum]))
- return false;
- // bypass next word and following spaces
- while (nextNum < currentLine.length())
- {
- if (!isLegalNameChar(currentLine[nextNum])
- && !isWhiteSpace(currentLine[nextNum]))
- break;
- nextNum++;
- }
- // check for characters that indicate an operator
- if (currentLine[nextNum] == ','
- || currentLine[nextNum] == '}'
- || currentLine[nextNum] == ')'
- || currentLine[nextNum] == '(')
- return true;
- return false;
- }
- // Reset the flags that indicate various statement information.
- void ASFormatter::resetEndOfStatement()
- {
- foundQuestionMark = false;
- foundNamespaceHeader = false;
- foundClassHeader = false;
- foundStructHeader = false;
- foundInterfaceHeader = false;
- foundPreDefinitionHeader = false;
- foundPreCommandHeader = false;
- foundPreCommandMacro = false;
- foundTrailingReturnType = false;
- foundCastOperator = false;
- isInPotentialCalculation = false;
- isSharpAccessor = false;
- isSharpDelegate = false;
- isInObjCMethodDefinition = false;
- isInObjCInterface = false;
- isInObjCSelector = false;
- isInEnum = false;
- isInExternC = false;
- elseHeaderFollowsComments = false;
- nonInStatementBrace = 0;
- while (!questionMarkStack->empty())
- questionMarkStack->pop_back();
- }
- // Find the colon alignment for Objective-C method definitions and method calls.
- int ASFormatter::findObjCColonAlignment() const
- {
- assert(currentChar == '+' || currentChar == '-' || currentChar == '[');
- assert(getAlignMethodColon());
- bool isFirstLine = true;
- bool haveFirstColon = false;
- bool foundMethodColon = false;
- bool isInComment_ = false;
- bool isInQuote_ = false;
- char quoteChar_ = ' ';
- int sqBracketCount = 0;
- int colonAdjust = 0;
- int colonAlign = 0;
- string nextLine_ = currentLine;
- ASPeekStream stream(sourceIterator);
- // peek next line
- while (sourceIterator->hasMoreLines() || isFirstLine)
- {
- if (!isFirstLine)
- nextLine_ = stream.peekNextLine();
- // parse the line
- haveFirstColon = false;
- nextLine_ = ASBeautifier::trim(nextLine_);
- for (size_t i = 0; i < nextLine_.length(); i++)
- {
- if (isWhiteSpace(nextLine_[i]))
- continue;
- if (nextLine_.compare(i, 2, "/*") == 0)
- isInComment_ = true;
- if (isInComment_)
- {
- if (nextLine_.compare(i, 2, "*/") == 0)
- {
- isInComment_ = false;
- ++i;
- }
- continue;
- }
- if (nextLine_[i] == '\\')
- {
- ++i;
- continue;
- }
- if (isInQuote_)
- {
- if (nextLine_[i] == quoteChar_)
- isInQuote_ = false;
- continue;
- }
- if (nextLine_[i] == '"'
- || (nextLine_[i] == '\'' && !isDigitSeparator(nextLine_, i)))
- {
- isInQuote_ = true;
- quoteChar_ = nextLine_[i];
- continue;
- }
- if (nextLine_.compare(i, 2, "//") == 0)
- {
- i = nextLine_.length();
- continue;
- }
- // process the current char
- if ((nextLine_[i] == '{' && (currentChar == '-' || currentChar == '+'))
- || nextLine_[i] == ';')
- goto EndOfWhileLoop; // end of method definition
- if (nextLine_[i] == ']')
- {
- --sqBracketCount;
- if (sqBracketCount == 0)
- goto EndOfWhileLoop; // end of method call
- }
- if (nextLine_[i] == '[')
- ++sqBracketCount;
- if (isFirstLine) // colon align does not include the first line
- continue;
- if (sqBracketCount > 1)
- continue;
- if (haveFirstColon) // multiple colons per line
- continue;
- // compute colon adjustment
- if (nextLine_[i] == ':')
- {
- haveFirstColon = true;
- foundMethodColon = true;
- if (shouldPadMethodColon)
- {
- int spacesStart;
- for (spacesStart = i; spacesStart > 0; spacesStart--)
- if (!isWhiteSpace(nextLine_[spacesStart - 1]))
- break;
- int spaces = i - spacesStart;
- if (objCColonPadMode == COLON_PAD_ALL || objCColonPadMode == COLON_PAD_BEFORE)
- colonAdjust = 1 - spaces;
- else if (objCColonPadMode == COLON_PAD_NONE || objCColonPadMode == COLON_PAD_AFTER)
- colonAdjust = 0 - spaces;
- }
- // compute alignment
- int colonPosition = i + colonAdjust;
- if (colonPosition > colonAlign)
- colonAlign = colonPosition;
- }
- } // end of for loop
- isFirstLine = false;
- } // end of while loop
- EndOfWhileLoop:
- if (!foundMethodColon)
- colonAlign = -1;
- return colonAlign;
- }
- // pad an Objective-C method colon
- void ASFormatter::padObjCMethodColon()
- {
- assert(currentChar == ':');
- int commentAdjust = 0;
- char nextChar = peekNextChar();
- if (objCColonPadMode == COLON_PAD_NONE
- || objCColonPadMode == COLON_PAD_AFTER
- || nextChar == ')')
- {
- // remove spaces before
- for (int i = formattedLine.length() - 1; (i > -1) && isWhiteSpace(formattedLine[i]); i--)
- {
- formattedLine.erase(i);
- --commentAdjust;
- }
- }
- else
- {
- // pad space before
- for (int i = formattedLine.length() - 1; (i > 0) && isWhiteSpace(formattedLine[i]); i--)
- if (isWhiteSpace(formattedLine[i - 1]))
- {
- formattedLine.erase(i);
- --commentAdjust;
- }
- appendSpacePad();
- }
- if (objCColonPadMode == COLON_PAD_NONE
- || objCColonPadMode == COLON_PAD_BEFORE
- || nextChar == ')')
- {
- // remove spaces after
- int nextText = currentLine.find_first_not_of(" \t", charNum + 1);
- if (nextText == (int)string::npos)
- nextText = currentLine.length();
- int spaces = nextText - charNum - 1;
- if (spaces > 0)
- {
- // do not use goForward here
- currentLine.erase(charNum + 1, spaces);
- spacePadNum -= spaces;
- }
- }
- else
- {
- // pad space after
- int nextText = currentLine.find_first_not_of(" \t", charNum + 1);
- if (nextText == (int)string::npos)
- nextText = currentLine.length();
- int spaces = nextText - charNum - 1;
- if (spaces == 0)
- {
- currentLine.insert(charNum + 1, 1, ' ');
- spacePadNum += 1;
- }
- else if (spaces > 1)
- {
- // do not use goForward here
- currentLine.erase(charNum + 1, spaces - 1);
- spacePadNum -= spaces - 1;
- }
- }
- spacePadNum += commentAdjust;
- }
- // Remove the leading '*' from a comment line and indent to the next tab.
- void ASFormatter::stripCommentPrefix()
- {
- int firstChar = formattedLine.find_first_not_of(" \t");
- if (firstChar < 0)
- return;
- if (isInCommentStartLine)
- {
- // comment opener must begin the line
- if (formattedLine.compare(firstChar, 2, "/*") != 0)
- return;
- int commentOpener = firstChar;
- // ignore single line comments
- int commentEnd = formattedLine.find("*/", firstChar + 2);
- if (commentEnd != -1)
- return;
- // first char after the comment opener must be at least one indent
- int followingText = formattedLine.find_first_not_of(" \t", commentOpener + 2);
- if (followingText < 0)
- return;
- if (formattedLine[followingText] == '*' || formattedLine[followingText] == '!')
- followingText = formattedLine.find_first_not_of(" \t", followingText + 1);
- if (followingText < 0)
- return;
- if (formattedLine[followingText] == '*')
- return;
- int indentLen = getIndentLength();
- int followingTextIndent = followingText - commentOpener;
- if (followingTextIndent < indentLen)
- {
- string stringToInsert(indentLen - followingTextIndent, ' ');
- formattedLine.insert(followingText, stringToInsert);
- }
- return;
- }
- // comment body including the closer
- if (formattedLine[firstChar] == '*')
- {
- if (formattedLine.compare(firstChar, 2, "*/") == 0)
- {
- // line starts with an end comment
- formattedLine = "*/";
- }
- else
- {
- // build a new line with one indent
- int secondChar = formattedLine.find_first_not_of(" \t", firstChar + 1);
- if (secondChar < 0)
- {
- adjustChecksumIn(-'*');
- formattedLine.erase();
- return;
- }
- if (formattedLine[secondChar] == '*')
- return;
- // replace the leading '*'
- int indentLen = getIndentLength();
- adjustChecksumIn(-'*');
- // second char must be at least one indent
- if (formattedLine.substr(0, secondChar).find('\t') != string::npos)
- {
- formattedLine.erase(firstChar, 1);
- }
- else
- {
- int spacesToInsert = 0;
- if (secondChar >= indentLen)
- spacesToInsert = secondChar;
- else
- spacesToInsert = indentLen;
- formattedLine = string(spacesToInsert, ' ') + formattedLine.substr(secondChar);
- }
- // remove a trailing '*'
- int lastChar = formattedLine.find_last_not_of(" \t");
- if (lastChar > -1 && formattedLine[lastChar] == '*')
- {
- adjustChecksumIn(-'*');
- formattedLine[lastChar] = ' ';
- }
- }
- }
- else
- {
- // first char not a '*'
- // first char must be at least one indent
- if (formattedLine.substr(0, firstChar).find('\t') == string::npos)
- {
- int indentLen = getIndentLength();
- if (firstChar < indentLen)
- {
- string stringToInsert(indentLen, ' ');
- formattedLine = stringToInsert + formattedLine.substr(firstChar);
- }
- }
- }
- }
- } // end namespace astyle
|