RE> What I?m not sure how to do (well, I?m unwilling to spend the time, 
because WTH) is capture spaces within a variable name.

If anyone puts spaces in a variable name, well, they deserve what they 
get.

I also realized that constructions such as ARRAY 
TEXT($aMyTextArray;$ArraySize) contain both a declaration and a use of a 
variable, and also John DeSoi replied with a good idea to "smash" all 
strings enclosed in double quotes into just the double quotes, so that any 
$ contained within are not considered, so here is Version 2 of the method, 
that takes care of both, and also incorporates the new underscore-version 
of the regex:

*** Version 2 ***


//Bob Miller 04/30/18 CheckLocalDeclarations - called by macro to check 
that all local variables are declared.
//Method name is passed by the macro as $1
//This method calls itself in a new process if only one parm is sent (eg. 
when it is called by the macro).

C_TEXT($1;$2;$MethodName;$AllCodeButDeclarations;$LineDeclarationBlock;$ArrayDeclarationBlock;$NewProcessFlag)
C_TEXT($MethodCode;$CR)
C_TEXT($RegEx;$CodeLine)
C_LONGINT($N;$NumLines;$ProcNo;$L;$NumDeclarations;$WhereCommentBegins;$WhereSemi;$WhereDollar)
C_POINTER($DummyPtr)
$CR:=Char(Carriage return)//I know I should use a constant, yes...still 
haven't got around to this.

Case of 
: (Count parameters=1)//if called with only a single parm, then this 
method re-opens itself in its own process
//Note below on New Process: I chose to leave the * off so I can run it 
again if I want, a new window is opened
$ProcNo:=New process(Current method name;256*1024;Current method 
name;$1;"NewProcess")
BRING TO FRONT($ProcNo)


: (Count parameters=2)
$MethodName:=$1
$NewProcessFlag:=$2//existence of $2 simply means we are in a new process, 
that's all it does

METHOD GET CODE($MethodName;$MethodCode)

ARRAY TEXT($aMethodCodeArr;0)
TextToArrayList (->$MethodCode;->$aMethodCodeArr;"";"";"NoSort")//this 
takes text and puts each line as an array element



$NumLines:=Size of array($aMethodCodeArr)

For ($N;1;$NumLines)//go through all the lines of the method, separate 
into 4 pieces: variable declarations, array declarations, code, and 
comments.
//We don't keep any comments.I don't know why I want to keep variable 
declarations separate from array declarations; it makes me feel better.

$CodeLine:=$aMethodCodeArr{$N}//this is one line of code.We examine it.

$WhereCommentBegins:=Position("//";$CodeLine)//find and remove all 
comments; they may contain local variable references, such as unused code
If ($WhereCommentBegins>=1)
$CodeLine:=Substring($CodeLine;1;$WhereCommentBegins-1)
End if 

$CodeLine:=Replace string($CodeLine;Char(Tab);"")//remove leading TAB's, 
we want what we're looking for to be at position 1
$CodeLine:=DeLBlank ($CodeLine)//remove leading spaces from the code line, 
so we're assured what we are looking for will be at position 1
$CodeLine:=RemoveQuotedStrings ($CodeLine)//Thanks to John DeSoi; remove 
anything in double quotes, to prevent catching any $ that would be there


Case of 
: (Position("C_";$CodeLine)=1)//this is a C_BOOLEAN or C_TEXT or 
C_Something declaration command and now will be at position 1 (no tabs, no 
spaces)
$LineDeclarationBlock:=$LineDeclarationBlock+$CodeLine+$CR//this is all 
the code containing declarations


: (Position("ARRAY ";$CodeLine)=1)//this is an ARRAY BOOLEAN or ARRAY TEXT 
or ARRAY Something command
$WhereSemi:=Position(";";$CodeLine)
If ($WhereSemi>0)

$WhereDollar:=Position("$";$CodeLine;$WhereSemi)`Added this section in 
version 2:
If ($WhereDollar>0)//if there is a dollar sign after the semicolon, eg 
ARRAY LONGINT($aLongintArray;$SizeOfArray) - then add this portion to 
$AllCodeButDeclarations
$AllCodeButDeclarations:=$AllCodeButDeclarations+Substring($CodeLine;$WhereSemi;Length($CodeLine))+$CR
End if 

$CodeLine:=Substring($CodeLine;1;$WhereSemi)+"0)"//force line to look only 
at the array declaration, because there could be a var after this

End if 
$ArrayDeclarationBlock:=$ArrayDeclarationBlock+$CodeLine+$CR//this is all 
the code containing array declarations

Else 
// this is not a declaration line
If ($CodeLine#"")//make sure it is not a blank line; build up the code 
WITHOUT the declarations; we'll
//later examine this to get all the variables that are in use
$AllCodeButDeclarations:=$AllCodeButDeclarations+$CodeLine+$CR
End if //$CodeLine#""

End case 
End for //$N;1;$NumLines

// I haven't tried it, but Patrick Emanuel suggested this: 
"(?mi-s)(\\b[[:alpha:]][\\w+]*\\b)[?=\\:|\\;|\\)|\\>|\\<|\\{|\\}|\\]|\\[|\\r|\\n]|(\\$[\\w+]*\\b)|(<>[[:alpha:]][\\w+]*\\b)"
$RegEx:="\\$[_a-zA-Z0-9]*"//many thanks to Lee Hinde for this, horray 
(version 2, with underscore)!

// ++++++++++++Pull all declared local variables out
ARRAY TEXT($aDeclaredLocals;0)// array of all locals pulled out of our 
code containing declaractions; these are "Declared Locals"
ARRAY TEXT($aUniqueDeclaredLocals;0)// Same as above, reduced to a single 
instance for each local var
ParseRegexToArray ($LineDeclarationBlock;$RegEx;->$aDeclaredLocals)//Takes 
the text $1, uses the RegEx $2, puts all matches in array $3
ARR_Distinct (->$aDeclaredLocals;->$aUniqueDeclaredLocals)//pulls out any 
duplicates, so only 1 instance is in $2

ARRAY TEXT($aLocalDeclaredMultiple;0)
ARRAY LONGINT($aLocalDeclaredMultipleCount;0)
ARRAY LONGINT($aIndex;0)

If (Size of array($aDeclaredLocals)#Size of 
array($aUniqueDeclaredLocals))//check if any var is declared twice
ARR_SizeArrays (0;->$aIndex)
For ($L;1;Size of array($aUniqueDeclaredLocals))
$NumDeclarations:=ARR_FindInArray_All 
(->$aUniqueDeclaredLocals{$L};->$aDeclaredLocals;->$aIndex)//Takes the 
text $1,
//looks for it in array $2, returns the number of times it finds it in 
$0.If we found it more than once, it was declared more than once.
If ($NumDeclarations>1)
APPEND TO ARRAY($aLocalDeclaredMultiple;$aUniqueDeclaredLocals{$L})
APPEND TO ARRAY($aLocalDeclaredMultipleCount;$NumDeclarations)
End if 
End for 
End if //Size of array($aDeclaredLocals)#Size of 
array($aUniqueDeclaredLocals)


// ++++++++++++Pull all declared local arrays out
ARRAY TEXT($aDeclaredArrays;0)//Get array of all declared local arrays, 
just like above
ARRAY TEXT($aUniqueDeclaredArrays;0)
ParseRegexToArray ($ArrayDeclarationBlock;$RegEx;->$aDeclaredArrays)
ARR_Distinct (->$aDeclaredArrays;->$aUniqueDeclaredArrays)

If (Size of array($aDeclaredArrays)#Size of 
array($aUniqueDeclaredArrays))//check if any var is declared twice
ARR_SizeArrays (0;->$aIndex)
For ($L;1;Size of array($aUniqueDeclaredArrays))
$NumDeclarations:=ARR_FindInArray_All 
(->$aUniqueDeclaredArrays{$L};->$aDeclaredArrays;->$aIndex)
If ($NumDeclarations>1)
APPEND TO ARRAY($aLocalDeclaredMultiple;$aUniqueDeclaredArrays{$L})
APPEND TO ARRAY($aLocalDeclaredMultipleCount;$NumDeclarations)
End if 
End for 
End if //Size of array($aDeclaredArrays)#Size of 
array($aUniqueDeclaredArrays)


// ++++++++++++Pull all the local variables used in the code
ARRAY TEXT($aVarsUsed;0)//Get array of all the local vars used in the code 
(not declared, but actually used)
ARRAY TEXT($aUniqueVarsUsed;0)
ParseRegexToArray ($AllCodeButDeclarations;$RegEx;->$aVarsUsed)
ARR_Distinct (->$aVarsUsed;->$aUniqueVarsUsed)


// ++++++++++++Compare the set of declared locals with the set of "locals 
used in code"
//Note: ARR_Union, ARR_Subtract are part of a tech note by Charlie Vaas 
TN10-05 ArrayUtilities
ARRAY TEXT($aDeclaredAllVars;0)
ARR_Union 
(->$aUniqueDeclaredLocals;->$aUniqueDeclaredArrays;->$aDeclaredAllVars)//combine
 
the declared vars with the declared arrays

ARRAY TEXT($aUsedNotDeclared;0)
ARR_Subtract 
(->$aUniqueVarsUsed;->$aDeclaredAllVars;->$aUsedNotDeclared)//do some 
array DIFFERENCE to get vars that are not declared

ARRAY TEXT($aDeclaredNotUsed;0)
ARR_Subtract 
(->$aDeclaredAllVars;->$aUniqueVarsUsed;->$aDeclaredNotUsed)//do some 
array DIFFERENCE to get vars that are declared not used


// ++++++++++++We have our results in arrays, prepare text to display on a 
dialog
C_TEXT(vMsgText;vMsgText1)//for CheckLocalVarsDlog - replace when we can 
send parms directly to forms in v16 (declaration is here because we are in 
our own process)
vMsgText:=ArrayToText (->$aUsedNotDeclared;"; ")//this takes an array and 
converts the elements to a long text string with elements delimited by 
semicolon
vMsgText1:=ArrayToText (->$aDeclaredNotUsed;$CR)//ditto, delimited by 
carriage return

vMsgText2:=""
For ($L;1;Size of array($aLocalDeclaredMultiple))//build up text string 
showing any vars that were declared more than once, along with the number 
of times it was declared
vMsgText2:=vMsgText2+$aLocalDeclaredMultiple{$L}+" 
("+String($aLocalDeclaredMultipleCount{$L})+"x)"+$CR
End for 

If (vMsgText+vMsgText1+vMsgText2="")
//do nothing, no need to open window if everything is OK (but YOU could 
say, "Everything seems to be OK" in fine 4D form if you wanted to)
Else 
// I fully recognize it is now bad form to use process vars to communicate 
with a form, but hey, I'm still in v15...
MyOpenFormWindow ($DummyPtr;"CheckLocalVarsDlog";"Check Local Variables: 
"+$MethodName;0;*)//$DummyPtr tells the method this is a project form, not 
a table form.
//The form is CheckLocalVarsDlog, the next parm is the window title, then 
the window type, then star keeps the window open while this method 
completes.
End if 


End case 
//



Bob Miller
Chomerics, a division of Parker Hannifin Corporation



llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
"PLEASE NOTE: The preceding information may be confidential or privileged. It 
only should be used or disseminated for the purpose of conducting business with 
Parker. If you are not an intended recipient, please notify the sender by 
replying to this message and then delete the information from your system. 
Thank you for your cooperation."
**********************************************************************
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: https://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:4d_tech-unsubscr...@lists.4d.com
**********************************************************************

Reply via email to