//TH-Header //***************************************************************************************** // Copyright (c) 2018 VDF-Guidance // All rights reserved. // // $FileName : cSciLexerRefactor.pkg // $ProjectName : TheHammer3 // $Authors : // $Created : 02.09.2018 00:16 // // Contents: // Additional class to move the refactoring logic into a subclass // //***************************************************************************************** //TH-RevisionStart // ******************** // MODIFICATION SUMMARY // ******************** // ####### DD/MM/YYYY WHO COMMENT //TH-RevisionEnd Use cSciLexer.pkg Use Messagebox2.dg Struct tRefactorResponse String sObject Integer eResponse Boolean bPadded End_Struct Enum_List Define CI_NoCaseStatement For 0 Define CI_CaseBegin Define CI_CaseCondition Define CI_CaseBreak Define CI_CaseEnd End_Enum_List Class cSciLexerRefactor is a cSciLexer Procedure Construct_Object Forward Send Construct_Object Property Boolean pbRefactorPadReplaceString True Property Boolean pbIndentCaseBreak True // Indent on "case break", set to false if you don't want that. Property tRefactorResponse[] pRefactorResponse // Remember the refactoring response per object End_Procedure Function RefactorReplaceObjectConfirmation Integer iLine String sFind String sReplace Boolean bPadded Boolean bRemember Returns Integer Integer eResponse String szAnnotate String sCheckbox1 String sCheckbox2 tmbMessageBox mb Move ("Do you want to replace '"+sFind+"' with '"+sReplace+"' ?") To szAnnotate Send GotoLine iLine Send EditorMessage SCI_ANNOTATIONSETSTYLE iLine STYLE_CALLTIP Send EditorMessage SCI_ANNOTATIONSETTEXT iLine (AddressOf(szAnnotate)) Send EditorMessage SCI_ANNOTATIONSETVISIBLE ANNOTATION_BOXED Move "Keep same width padded with spaces" To sCheckbox1 Move "Remember the choice for this object" To sCheckbox2 Get mbYesNoCancelBox "Change into suggestion?" "Question" MB_DEFBUTTON2 0 sCheckbox1 bPadded To mb Move sCheckbox2 To mb.Message[2].sMessage Move True To mb.Message[2].bCheckbox Move bRemember To mb.Message[2].bChecked Send ShowMessageBox (&mb) Move (mb.iRetVal ior If(mb.message[1].bchecked,MBR_CHECKED,0)) To mb.iRetVal Move (mb.iRetVal ior If(mb.message[2].bchecked,MBR_CHECKED2,0)) To mb.iRetVal Move mb.iRetVal To eResponse Move "" To szAnnotate Send EditorMessage SCI_ANNOTATIONSETTEXT iLine (AddressOf(szAnnotate)) Send EditorMessage SCI_ANNOTATIONSETVISIBLE ANNOTATION_HIDDEN Function_Return eResponse End_Function // // Sometimes we already know that we do not have to offer a replacement // Function IsDropSelfReplaceTargetValid String sReplace Returns Boolean Boolean bIsValid Move True To bIsValid Move (Lowercase(sReplace)) To sReplace If (sReplace = "parent") Begin Move False To bIsValid End Function_Return bIsValid End_Function Procedure RefactorLocateSourceObject String sLine Integer iSelfPos Integer iLength Integer ByRef iPosStart Integer ByRef iPosEnd Integer ByRef iLevel Boolean bIsParam Integer iObjStart Integer iNext String sChar Move False to bIsParam Move (iPosStart+4) To iObjStart Move (Replaces(Character(9),sLine," ")) To sLine Move (Pos("(",sLine,iObjStart)) To iPosStart // search for ( after " to " (or for functions after " of " Move (Pos(")",sLine,iPosStart)) To iPosEnd // find first close quote If (iPosStart>iObjStart) Begin // Test if the located (Self) is an object reference or For iNext From iObjStart To iPosStart // part of a passed parameter. Move (Mid(sLine,1,iNext)) To sChar If (sChar <> " ") Begin Move True To bIsParam Move iPosStart To iNext // break the loop End Loop End If (iSelfPos>=iPosStart and iSelfPos0) Begin For iChar From 1 To (iPos-1) Move (Overstrike(" ",sLine,iChar)) To sLine Loop End End_Procedure // // With our refactoring logic if a line starts with if, else or on_key then the logic won't see // send/get/set as the first string and that complicates our detection. // What this does is simply overwrite everything with spaces before our methods if // we have such a compound statement. // The variable sLine is not always lowercase. // Procedure ClearFirstCompoundBeforeMethod String ByRef sLine Integer iPos String sLtrimLine Move (lowercase(LTrim(sLine))) To sLTrimLine If (Left(sLtrimLine,3)="if " or Left(sLtrimLine,5)="else " or Left(sLtrimLine,7)="on_key ") Begin // a line that starts with an if or else can still call a method Move (Pos("send ",lowercase(sLine))) To iPos If (iPos=0) ; Move (Pos("get ",lowercase(sLine))) To iPos If (iPos=0) ; Move (Pos("set ",lowercase(sLine))) To iPos Send WipeUntilPosition iPos (&sLine) End End_Procedure Procedure RefactorDropSelf Boolean bAutoResponse Boolean bSuggestReplace Boolean bPadded Boolean bRemember Boolean bCanceled Integer iPos Integer iPosStart Integer iPosEnd Integer iLevel Integer iStartLine Integer iLine Integer iLineCount Integer iLength Integer eResponse String sLine String sFind String sReplace String sPad Move False To bCanceled Send ClearRefactorAutoResponse Get pbRefactorPadReplaceString To bPadded Get CurrentLine To iStartLine Get SC_LineCount To iLineCount For iLine From iStartLine To iLineCount Move False To bSuggestReplace Get PreParsedLine iLine To sLine Move (Lowercase(sLine)) To sLine Move (Pos("(self)",sLine)) To iPos If (iPos>0) Begin Send ClearFirstCompoundBeforeMethod (&sLine) Move (Pos("(self)",sLine)) To iPos End If (iPos>0) Begin // only check if there's a self in the line If (Left(LTrim(sLine),5)="send ") Begin Move (Pos(" to ",sLine)) To iPosStart If (iPosStart=0) ; Move (Pos(" of ",sLine)) To iPosStart If (iPosStart<>0) Begin Move (Length(sLine)) To iLength Send RefactorLocateSourceObject sLine iPos iLength (&iPosStart) (&iPosEnd) (&iLevel) Get Value iLine To sLine // real line data Move (Mid(sLine,iPosEnd-iPosStart+1,iPosStart)) To sFind Move sFind To sReplace If (iLevel=2) Begin // not supporting multiple levels atm Move (Left(sReplace,RightPos("(",sReplace)-1)) To sReplace Move (Replace("(",sReplace,"")) To sReplace End If (iLevel=2) Begin Get IsDropSelfReplaceTargetValid sReplace To bSuggestReplace End End End If (Left(LTrim(sLine),4)="get " or Left(LTrim(sLine),4)="set ") Begin Move (Pos(" of ",sLine)) To iPosStart If (iPosStart<>0) Begin Move (Pos(" to ",sLine)) To iLength // don't search past the " to " bit If (iPos"") Begin Get LineIsDfImage iLine sLine To bIsDfImage If (bIsDfImage=False) Begin Get LineIsCaseStatement sLine To eCaseStatus If (eCaseStatus<>CI_NoCaseStatement) Begin If (eCaseStatus=CI_CaseBegin) Begin Increment iCaseLevel End Else If (eCaseStatus=CI_CaseEnd) Begin Decrement iCaseLevel End End Get LineIsSingleLineIfElseStatement iLine sLine bIsIfElseIndent To bIsIfElse Get LineIsCommandMacro iLine sLine bMacroCommandOpen To bMacroCommandOpen If (bMacroCommandOpen) Begin Move sLine To sLineSave End Move (LTrim(sLine)) To sLine If (bIsIfElseIndent) Begin // don't indent on begin after single line if/else If (Left(Lowercase(sLine),6)="begin ") Begin // scenario pointed out by Mike (Starzen), see Move false To bIsIfElseIndent // bug https://projects.vdf-guidance.com/issues/127 End End Get ReIndentLineIndentation iLine iLineCount iTabSize bUseTabs (&iPrevLevel) To sIndent If (iCaseLevel>0) Begin If (eCaseStatus=CI_NoCaseStatement or eCaseStatus=CI_CaseEnd or (eCaseStatus=CI_CaseBreak and pbIndentCaseBreak(Self))) Begin Move (Repeat(sTab,iCaseLevel)) To sTabLevel Move (sIndent+sTabLevel) To sIndent End Else Begin Move (Repeat(sTab,iCaseLevel-1)) To sTabLevel Move (sIndent+sTabLevel) To sIndent End End If (bIsIfElseIndent) Begin Move (sIndent+sTab) To sIndent End Move (sIndent+sLine) To sLine If (bMacroCommandOpen) Begin Move sLineSave To sLine End Move bIsIfElse To bIsIfElseIndent End End If (pbUtf8Mode(Self)=False) Begin Get Utf8ToEditorFormat sLine to sLine End Move (StringToUCharArray(sLine)) to ucaLine Move (AppendArray(TextData,ucaLine)) To TextData Loop Move 0 To TextData[SizeOfArray(TextData)] // add a zero at the end Move (AddressOf(TextData)) To aTextData If (aTextData<>0) Begin Send EditorMessage SCI_CLEARALL 0 0 Send EditorMessage SCI_SETTEXT 0 aTextData End Send EditorMessage SCI_ENDUNDOACTION Send GotoLine iCurrentLine End_Procedure Function RefactorReIndent String[] ByRef asSourceFile Returns Integer Integer iRetval Boolean bErr Move 0 to iRetval Move Err to bErr Send RefactorReIndent If (Err = False) Begin Move 1 to iRetval End Move bErr to Err Function_Return iRetval End_Function End_Class