[CDK] Check functions for returns

Discussion forum about all things Team Developer 7.x
gaiflo
Germany
Posts: 20
Joined: 29 Oct 2019, 12:00
Location: Berlin

[CDK] Check functions for returns

Post by gaiflo » 06 Nov 2019, 11:28

So i want to write an app that checks an app and its libraries for faulty returns. As in: If a function has a return defined but none in the Actioncode or the other way around - if the function has a return given back in the Actioncode but none defined.
So far so good.

I think i got it right but i get 0 faults for any app i use it on.

Even one where i know that there are "faulty" functions. (Return defined but none given in the code, No Return defined but something is returned in the code)


Also though, when i'm looping through the outline of the function, when i'm INSIDE the Actionblock, and no actual return is called in the function which is looked up, it still comes back TRUE because one item is CDK_IT_Return.... This bugs me extremely....


Functions look like this:

Code: Select all

Function: ProcessFunction
	Description: Returns TRUE if it has a return in the outline - returns FALSE if it doesn't have a return in the outline
	Returns
		Boolean:
	Parameters
		FunctionalVar: cdkp_FunctionItem
			Class: cdkFunction
	Static Variables
	Local variables
		Number: nOutline
		Boolean: bRet
		Number: nItem
		Number: nNextItem
		Number: nItemPrev
		Number: nType
	Actions
		Set bRet = FALSE
		Set nOutline = cdkp_FunctionItem.GetOutline(  )
		Set nItem = SalOutlineTop( nOutline )
		Set nItemPrev = nItem
		While nItem != 0
			Set nType = SalOutlineItemType( nOutline, nItem )
			Set nNextItem = SalOutlineNextLine( nOutline, nItem )
			If nType = CDK_IT_ActionsBlock
				While nItem != 0
					Set nType = SalOutlineItemType( nOutline, nItem )
					Set nNextItem = SalOutlineNextLine( nOutline, nItem )
					If nType = CDK_IT_Return
						Return TRUE
					Set nItemPrev = nItem
					Set nItem = nNextItem
			Set nItemPrev = nItem
			Set nItem = nNextItem
		Return FALSE

Code: Select all

Function: CheckFunctionForReturns
	Description:
	Returns
	Parameters
		FunctionalVar: cdkp_FunctionItem
			Class: cdkFunction
		Number: nWrongReturns
	Static Variables
	Local variables
		String: sReturnType
	Actions
		If cdkp_FunctionItem.GetReturnType( sReturnType )
			! Return defined 
			If NOT ProcessFunction(cdkp_FunctionItem)
				Set nWrongReturns = nWrongReturns + 1
		Else
			! Return not defined
			If ProcessFunction(cdkp_FunctionItem)
				Set nWrongReturns = nWrongReturns + 1
What am i doing wrong?
TestFunctions.zip
xxxr.apt is the file which should be opened and used. The testCDKParser.app will be parsed.
You do not have the required permissions to view the files attached to this post.
Last edited by gaiflo on 06 Nov 2019, 12:22, edited 3 times in total.

Dave Rabelink
Founder/Site Admin
Founder/Site Admin
Netherlands
Posts: 1358
Joined: 24 Feb 2017, 09:12
Location: Gouda, The Netherlands

Re: [CDK] Check functions for returns

Post by Dave Rabelink » 06 Nov 2019, 12:14

Better post the CDK application and your test source here, so we can spot any issue more easily.
Regards,
Dave Rabelink

Image
Articles and information on Team Developer Tips & Tricks Wiki
Download samples, documents and resources from TD Sample Vault
Videos on TDWiki YouTube Channel

gaiflo
Germany
Posts: 20
Joined: 29 Oct 2019, 12:00
Location: Berlin

Re: [CDK] Check functions for returns

Post by gaiflo » 06 Nov 2019, 12:23

Dave Rabelink wrote:
06 Nov 2019, 12:14
Better post the CDK application and your test source here, so we can spot any issue more easily.
Done - uploaded at the very bottom of the first post.

gaiflo
Germany
Posts: 20
Joined: 29 Oct 2019, 12:00
Location: Berlin

Re: [CDK] Check functions for returns

Post by gaiflo » 06 Nov 2019, 12:53

Okay - now i know one mistake i made. Which is that i defined the nWrongNumber as regular Number in the parameters but it should be a Receive Number because i want to add a value to it inside the functions.

That doesn't change the fact though that i get a CDK_IT_Return inside an CDK_IT_ActionsBlock when there is actually nothing returned...

Dave Rabelink
Founder/Site Admin
Founder/Site Admin
Netherlands
Posts: 1358
Joined: 24 Feb 2017, 09:12
Location: Gouda, The Netherlands

Re: [CDK] Check functions for returns

Post by Dave Rabelink » 06 Nov 2019, 13:10

I did have a quick look.

First I wonder why you are using SalOutline functions.
You should use the CDK classes which makes it easier to traverse the outline.

Also you do not process the actionsblock but scan the entire outline from the top.

In function: ProcessFunction, I see this:

Code: Select all

Set nItem = SalOutlineTop( nOutline )
Which means you start looking each line from the top item of the complete sourcefile.
You need to loop the actionsblock of the particular function.

To get the actionblock, you can call:

Code: Select all

cdkp_FunctionItem.GetActions( cActions )
cActions is an object of type cdkActionBlock.

This class has functions to start at the first line, step to next/previous/parent/child etc.
Regards,
Dave Rabelink

Image
Articles and information on Team Developer Tips & Tricks Wiki
Download samples, documents and resources from TD Sample Vault
Videos on TDWiki YouTube Channel

Dave Rabelink
Founder/Site Admin
Founder/Site Admin
Netherlands
Posts: 1358
Joined: 24 Feb 2017, 09:12
Location: Gouda, The Netherlands

Re: [CDK] Check functions for returns

Post by Dave Rabelink » 06 Nov 2019, 13:14

An example how to traverse functions can be seen in the source of the TD Profiling tool:

https://wiki.tdcommunity.net/index.php/ ... _Profiling

Have a look at the code. It shows how to scan functions, get the return type and detect returns within the action block.
This should point you to the way to implement your functionality.
Regards,
Dave Rabelink

Image
Articles and information on Team Developer Tips & Tricks Wiki
Download samples, documents and resources from TD Sample Vault
Videos on TDWiki YouTube Channel

gaiflo
Germany
Posts: 20
Joined: 29 Oct 2019, 12:00
Location: Berlin

Re: [CDK] Check functions for returns

Post by gaiflo » 06 Nov 2019, 13:18

You're the Champ Dave! Thanks again!! <3

gaiflo
Germany
Posts: 20
Joined: 29 Oct 2019, 12:00
Location: Berlin

Re: [CDK] Check functions for returns

Post by gaiflo » 12 Nov 2019, 13:45

Hey Dave,
me again....

i'm having some trouble traversing the ActionBlock...
Can you help me please? I don't know how to traverse it properly...

I've got this code but it never jumps into if statements...

Code: Select all

Call cdkp_FunctionItem.GetActions( cdkActionBlockItem )
 Set title = cdkActionBlockItem.Title(  )
 If title = "Return"
	Return TRUE
 While cdkActionBlockItem.Next(  ) 
	Set title = cdkActionBlockItem.Title(  )
	If title = "Return"
		Return TRUE
 Return FALSE

gaiflo
Germany
Posts: 20
Joined: 29 Oct 2019, 12:00
Location: Berlin

Re: [CDK] Check functions for returns

Post by gaiflo » 12 Nov 2019, 15:56

This would be how i would traverse it recursivly but i get an error: "Unrecoverable Error: The depth of function calls and messages has exceeded the capacity of the system."

This is my call:

Code: Select all

!!CB!! 134
Function: ProcessFunctionReturnsRecursive
	Description:
	Returns
		Boolean:
	Parameters
		FunctionalVar: p_ActionBlockItem
			Class: cdkActionBlock
	Static Variables
	Local variables
		Boolean: bReturn
		String: sTitle
	Actions
		Set sTitle = p_ActionBlockItem.Title(  )
		If sTitle = "Return"
			Set bReturn = TRUE
		If NOT bReturn 
			If p_ActionBlockItem.Child(  ) = TRUE
				Set bReturn = ProcessFunctionReturnsRecursive( p_ActionBlockItem )
				Call p_ActionBlockItem.Parent(  )
		If NOT bReturn 
			If p_ActionBlockItem.Next(  ) = TRUE
				Set bReturn = ProcessFunctionReturnsRecursive( p_ActionBlockItem )
		Return bReturn 

Dave Rabelink
Founder/Site Admin
Founder/Site Admin
Netherlands
Posts: 1358
Joined: 24 Feb 2017, 09:12
Location: Gouda, The Netherlands

Re: [CDK] Check functions for returns

Post by Dave Rabelink » 12 Nov 2019, 16:00

These are the steps.

First get the actionblock, then select the first item

Code: Select all

cdkp_FunctionItem.GetActions( cdkActionBlockItem )
cdkActionBlockItem.First( )

Then you need a loop. There you use combinations of the following CDK features

- Get the cdkActionBlockItem.Title( ) and check for "Return". Better check for the string constant CDK_TXT_RETURN
- Use cdkActionBlockItem.Child( ) to check if the current item has a child (if the line is an If statement, the child will be the line beneath the If
The function will return TRUE if the child was selected, FALSE otherwise
- Use cdkActionBlockItem.Next( ) to select the next line on the same level
The function will return TRUE if the next line was selected, FALSE otherwise
- Use cdkActionBlockItem.Parent( ) to select the parent line
The function will return TRUE if the parent line was selected, FALSE otherwise

So this is a standard implementation for "walk the tree".
You have to keep repeating the several selection functions and drill from Left to right (parent->child->child) and when no childs are present, keep scanning on the next line using child->next
And then drill from that item through all the childs.


The TDProfiling tool has a working example how to do this.
https://samples.tdcommunity.net/index.p ... build1.zip

File: \TDProfiling\TD_Sources\TDCodeGen.apt
Class : fcInsertTrace
Function: doFunction( )




Here a stripped version of that code which shows an implementation

Code: Select all

Call cActions.First( )
Set nLevel		= 0
Loop CODELOOP
	If not bGoUp and cActions.Title( ) = CDK_TXT_RETURN
		! YES, FOUND return statement.
	If not bGoUp and cActions.Child( )
		Set nLevel	= nLevel + 1
	Else If not bGoUp and cActions.Next( )
		Set nLevel		= nLevel
	Else If cActions.Parent( )
		Set nLevel	= nLevel - 1
		If not cActions.Next( )
			Set bGoUp		= TRUE
		Else
			Set bGoUp		= FALSE
	Else
		Break CODELOOP
Be aware that to check the existence of Return in the action block, you need to keep scanning the complete block and keep track of each trunk of the tree if it returns something.
As an example:

Code: Select all

If bLoaded
	Return 1
Else If bError
	Return 2
Else If bWarning
Else
	If bOk
		Return 5
The Else If bWarning line does not explicitly return a value
The If bOk, when false, will also not explicitly return a value

So stopping at the first occurrence of Return does not indicate the function is coded correctly. There are still 2 missing returns.
Regards,
Dave Rabelink

Image
Articles and information on Team Developer Tips & Tricks Wiki
Download samples, documents and resources from TD Sample Vault
Videos on TDWiki YouTube Channel

gaiflo
Germany
Posts: 20
Joined: 29 Oct 2019, 12:00
Location: Berlin

Re: [CDK] Check functions for returns

Post by gaiflo » 13 Nov 2019, 09:58

You're my saviour!
Thanks a lot for this elaborate answer!

Return to “General Discussion”

Who is online

Users browsing this forum: No registered users and 0 guests