Is it possible to find defined and unused variables?

Everything else that doesn't fall into one of the other PB categories.
miskox
User
User
Posts: 95
Joined: Sun Aug 27, 2017 7:37 pm
Location: Slovenia

Is it possible to find defined and unused variables?

Post by miskox »

It is possible to find variables that are DEFINEd and not actually used in the code? If not maybe this could be added to IDE?

Thanks.
Saso
User avatar
Caronte3D
Addict
Addict
Posts: 1053
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: Is it possible to find defined and unused variables?

Post by Caronte3D »

I think the variables are ever initialized to zero (integers) on "Define".
Some times if I need to know if a variable is used or not, I initialize it with a value I know the code not use.
Example:
If I only use positive numbers on a variable, then I Define it to -1, so I know if the variable was uses if >0

EDIT:
Seems I don't understand you enough, I was think you talk about runtime, not in the IDE :?
Last edited by Caronte3D on Fri Oct 14, 2022 7:28 am, edited 1 time in total.
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: Is it possible to find defined and unused variables?

Post by Sicro »

Unfortunately, this feature does not exist.

However, you can double-click on a variable name, which will highlight the name and all other occurrences in the code.

My IDE tool also searches for other occurrences of identifiers: SearchForUnusedIdentifiers
(You can also find the other required include files in this archive)

Sure, it's not a perfect solution.
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
miskox
User
User
Posts: 95
Joined: Sun Aug 27, 2017 7:37 pm
Location: Slovenia

Re: Is it possible to find defined and unused variables?

Post by miskox »

@sicro: Thanks. Will try that.

Saso
AZJIO
Addict
Addict
Posts: 1360
Joined: Sun May 14, 2017 1:48 am

Re: Is it possible to find defined and unused variables?

Post by AZJIO »

Sicro wrote: Wed Oct 12, 2022 6:18 pm SearchForUnusedIdentifiers
1. Can you add bit flags as a parameter to not output WinAPI functions and constants? Exclude structure fields that start with "\".
2. Is it possible to add the line number where the token is found?
3. Sometimes tokens are displayed that are not in the code.
4. Use \PureBasic\SDK\Syntax Highlighting\SyntaxHighlighting.dll
5. Hexadecimal numbers are not parsed correctly

Code: Select all

Mark(1)\color = $BBBBBB
Mark(2)\color = $32CEED
Mark(3)\color = 0
Mark(4)\color = $004284
Mark(5)\color = $0000FF
Mark(6)\color = $0084FF
Mark(7)\color = $00FFFF
Mark(8)\color = $00DD00
Mark(9)\color = $FF5B3B
Mark(10)\color = $FF3D9E
Mark(11)\color = $999999
Mark(12)\color = $FFFFFF

Code: Select all

=> aa
=> ff3d9e
=> ffffff
=> dd00
=> ffff
=> ceed
=> ff5b3b
=> bbbbbb
AZJIO
Addict
Addict
Posts: 1360
Joined: Sun May 14, 2017 1:48 am

Re: Is it possible to find defined and unused variables?

Post by AZJIO »

I got the variables using SyntaxHighlighting.dll and eliminated the variables that are repeated more than 1 time in the code. The result is saved to a file. This code is more compact.
I didn't remove the comments in the title to make it clear that I used a ready-made example, but instead of saving to a file, I exported tokens to a list.

Code: Select all

; ------------------------------------------------------------
;
;   PureBasic - Syntax hilightning dll example
;
;    (c) 2010 - Fantaisie Software
;
; ------------------------------------------------------------
;
; The SyntaxHilighting.dll provides the syntax parser of the 
; PureBasic IDE in form of a dll, so it can be easily reused
; to do other tasks as well.
;
; Some notes:
;
; - For speed reasons, the dll is not threadsave.
;
; - The hilighter does not handle unicode. It does however handle UTF8, so if
;   Unicode text should be parsed, convert it to UTF8 first.
;
; The dll exports only one function:
;
;    SyntaxHighlight(*Buffer, Length, @Callback(), EnableAsm)
;
; *Buffer and Length specify the text buffer to parse.
;
; Callback() must have the parameters as in the example below and will be called
; for each parsed token.
;
; If EnableAsm is set to nonzero, the parser will report asm keywords also outside of
; the special ! lines, just as the InlineAsm parser does.
;

; Color values returned in the Dll callback
;

EnableExplicit

Enumeration
	#SYNTAX_Text
	#SYNTAX_Keyword  
	#SYNTAX_Comment
	#SYNTAX_Constant
	#SYNTAX_String
	#SYNTAX_Function
	#SYNTAX_Asm
	#SYNTAX_Operator
	#SYNTAX_Structure
	#SYNTAX_Number
	#SYNTAX_Pointer
	#SYNTAX_Separator
	#SYNTAX_Label  
	#SYNTAX_Module
EndEnumeration

#Dll    = 0
#Input  = 0
#Output = 1

; Callback that is called from the dll. 
;
; NOTE: For performance reasons, whitespace characters (space, tab, newline)
; are returned together with the tokens they surround to reduce the number
; of required callback calls. If this is not desired, you must separate them
; here in the callback manually.
;
; The original buffer is not modified. The *Position parameter points to the
; current position in the original buffer. 
;

Declare.s LTrimChar(String$, TrimChar$ = #CRLF$ + #TAB$ + #FF$ + #VT$ + " ")
Declare.s RTrimChar(String$, TrimChar$ = #CRLF$ + #TAB$ + #FF$ + #VT$ + " ")

Global Result.string, LenT
Global InputFile$, OutputFile$, *Buffer, Length, *Point, LenT2, tmp$

Global NewMap Res_Text()
Global NewMap Res_Structure()
Global NewMap Res_Pointer()
;
Procedure AddToMap(Map Res(), tmp$)
	tmp$ = RTrimChar(tmp$)
	tmp$ = LTrimChar(tmp$)

	If FindMapElement(Res() , tmp$)
		Res(tmp$) + 1
	Else
		AddMapElement(Res() , tmp$)
		Res(tmp$) = 1
	EndIf
EndProcedure

Procedure Callback(*Position, Length, Color)
	Protected tmp$, tmp
	
	; In this example, we simply write the data as it is to the output
	; buffer, and just apply bold to keywords, and colors to functions and comments.
	;
	tmp$ = PeekS(*Position, Length, #PB_UTF8 | #PB_ByteLength)
	Select Color
		Case #SYNTAX_Text
			AddToMap(Res_Text(), tmp$)
			
		Case #SYNTAX_Structure
			AddToMap(Res_Structure(), tmp$)
			
		Case #SYNTAX_Pointer
			AddToMap(Res_Pointer(), tmp$)
			ForEach Res_Pointer()
				tmp = Asc(MapKey(Res_Pointer()))
				If tmp = '@' Or tmp = '?' ; удаляем взятие указателя, так как такой код никогда не является объявлением имени переменной
					DeleteMapElement(Res_Pointer())
				EndIf
			Next
			
	EndSelect
	
EndProcedure

; Simple example code. It loads a PB file and outputs a HTML file withs some
; coloring for functions, keywords and comments
;
If OpenLibrary(#Dll, #PB_Compiler_Home + "SDK\Syntax Highlighting\SyntaxHighlighting.dll")  
	; If OpenLibrary(#Dll, GetPathPart(ProgramFilename()) + "SyntaxHighlighting.dll")

	InputFile$ = OpenFileRequester("Select PB File", "", "*.pb*|*.pb*|All Files|*.*", 0)
; 	InputFile$ = "C:\Source\2022.10\test.pb"
	If InputFile$
		
		If ReadFile(#Input, InputFile$) ; And CreateFile(#Output, OutputFile$)
			Length = Lof(#Input)
			*Buffer = AllocateMemory(Length)
			
			If *Buffer
				ReadData(#Input, *Buffer, Length) ; читаем исходник в файл
				
				CallFunction(#Dll, "SyntaxHighlight", *Buffer, Length, @Callback(), 0)
; 				после вызова функции получаем заполненные списки элементов и пишем их в файл
; 				WriteStringN(#Output, "") ; пишем строку
				
				; вычисляем длину данных для вмещения частей текста
				LenT = 0

; 				ForEach Res_Text()
; 					Debug Res_Text()
; 				Next
				
				ForEach Res_Text()
; 					Debug Res_Text()
					If Res_Text() <> 1
						DeleteMapElement(Res_Text()) ; добавляет лексему если число вхождений больше чем 1
					EndIf
				Next
				ForEach Res_Text()
					LenT + StringByteLength(MapKey(Res_Text()), #PB_Unicode)
				Next
				ForEach Res_Structure()
; 					Debug Res_Structure()
					If Res_Structure() <> 1
						DeleteMapElement(Res_Structure())
					EndIf
				Next
				ForEach Res_Structure()
					LenT + StringByteLength(MapKey(Res_Structure()), #PB_Unicode)
				Next
				ForEach Res_Pointer()
; 					Debug Res_Pointer()
					If Res_Pointer() <> 1
						DeleteMapElement(Res_Pointer())
					EndIf
				Next
				ForEach Res_Pointer()
					LenT + StringByteLength(MapKey(Res_Pointer()), #PB_Unicode)
				Next
				
				LenT2 + MapSize(Res_Text())
				LenT2 + MapSize(Res_Structure())
				LenT2 + MapSize(Res_Pointer())
				LenT + LenT2*4
				If MapSize(Res_Text())
					LenT + 22 ; "=== Var ==="
				EndIf
				If MapSize(Res_Structure())
					LenT + 38 ; "=== Structure ==="
				EndIf
				If MapSize(Res_Pointer())
					LenT + 34 ; "=== Pointer ==="
				EndIf
				
				Result\s = Space(LenT) ; создаём строку забивая её пробелами
				*Point = @Result\s		; Получаем адрес строки
				; копируем очередной путь в указатель
				If MapSize(Res_Text())
					CopyMemoryString("=== Var ===" + #CRLF$, @*Point)
				EndIf
				ForEach Res_Text()
; 					CopyMemoryString(Str(Res_Text()), @*Point) ; добавляет число вхождений
					CopyMemoryString(MapKey(Res_Text()) + #CRLF$, @*Point)
				Next
				
				If MapSize(Res_Structure())
					CopyMemoryString(#CRLF$ + "=== Structure ===" + #CRLF$, @*Point)
				EndIf
				ForEach Res_Structure()
; 					CopyMemoryString(Str(Res_Structure()), @*Point)
					CopyMemoryString(MapKey(Res_Structure()) + #CRLF$, @*Point)
				Next
				
				If MapSize(Res_Pointer())
					CopyMemoryString(#CRLF$ + "=== Pointer ===" + #CRLF$, @*Point)
				EndIf
				ForEach Res_Pointer()
; 					CopyMemoryString(Str(Res_Pointer()), @*Point)
					CopyMemoryString(MapKey(Res_Pointer()) + #CRLF$, @*Point)
				Next
; 				WriteStringFormat(#Output, #PB_UTF8)
				; 				WriteString(#Output, Result\s) ; пишем строку
				
				tmp$ = PeekS(@Result\s, StringByteLength(Result\s, #PB_Unicode), #PB_Unicode)
; 				MessageRequester("", tmp$)
; 				WriteData(#Output, @Result\s, StringByteLength(Result\s, #PB_Unicode)) ; по умолчанию сохраняется в #PB_UTF8

			EndIf    
			
			CloseFile(#Input)
; 			CloseFile(#Output)
		EndIf
		
	EndIf  
	
	CloseLibrary(#Dll)
Else
	MessageRequester("", "Failed to open SyntaxHighlighting.dll")
	End
EndIf


If Asc(tmp$)
	If OpenWindow(0, 10, 10, 220, 600, "Unused (?)", #PB_Window_SystemMenu)
		EditorGadget(0, 0, 0, 220 , 600)
		SetGadgetText(0 , tmp$)
		StickyWindow(0, #True) 
		
		Repeat
			If WaitWindowEvent() = #PB_Event_CloseWindow
				CloseWindow(0)
				End
			EndIf
		ForEver
	EndIf
EndIf


; https://www.purebasic.fr/english/viewtopic.php?t=79183
Procedure.s LTrimChar(String$, TrimChar$ = #CRLF$ + #TAB$ + #FF$ + #VT$ + " ")
    Protected Len1, Len2, Blen, i, j
    Protected *memChar, *c.Character, *jc.Character

    Len1 = Len(TrimChar$)
    Len2 = Len(String$)
    Blen = StringByteLength(String$)

    If Not Asc(String$)
        ProcedureReturn ""
    EndIf

    *c.Character = @String$
    *memChar = @TrimChar$

    For i = 1 To Len2
        *jc.Character = *memChar

        For j = 1 To Len1
            If *c\c = *jc\c
                *c\c = 0
                Break
            EndIf
            *jc + SizeOf(Character)
        Next

        If *c\c
            String$ = PeekS(*c)
            Break
        EndIf
        *c + SizeOf(Character)
    Next

    ProcedureReturn String$
EndProcedure

; https://www.purebasic.fr/english/viewtopic.php?t=79183
Procedure.s RTrimChar(String$, TrimChar$ = #CRLF$ + #TAB$ + #FF$ + #VT$ + " ")
    Protected Len1, Len2, Blen, i, j
    Protected *memChar, *c.Character, *jc.Character

    Len1 = Len(TrimChar$)
    Len2 = Len(String$)
    Blen = StringByteLength(String$)

    If Not Asc(String$)
        ProcedureReturn ""
    EndIf

    *c.Character = @String$ + Blen - SizeOf(Character)
    *memChar = @TrimChar$

    For i = Len2 To 1 Step -1
        *jc.Character = *memChar

        For j = 1 To Len1
            If *c\c = *jc\c
                *c\c = 0
                Break
            EndIf
            *jc + SizeOf(Character)
        Next

        If *c\c
            Break
        EndIf
        *c - SizeOf(Character)
    Next

    ProcedureReturn String$
EndProcedure
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: Is it possible to find defined and unused variables?

Post by Sicro »

Hello AZJIO,

thanks for your feedback. I have improved the tool (and the dependent includes).
AZJIO wrote: Thu Oct 13, 2022 9:21 pm1. Can you add bit flags as a parameter to not output WinAPI functions and constants? Exclude structure fields that start with "\".
The following is now ignored by default:
  • All identifiers ending with an underscore. This also affects other things besides the WinAPI functions, but to keep the implementation simple I solved it this way.
  • Constants completely
  • Structure blocks/fields
AZJIO wrote: Thu Oct 13, 2022 9:21 pm2. Is it possible to add the line number where the token is found?
Yes, but the tool uses the PB compiler to merge the current code and all includes into one code, which is why the line numbers are then different than the user would expect.
AZJIO wrote: Thu Oct 13, 2022 9:21 pm3. Sometimes tokens are displayed that are not in the code.
The PB compiler is used for merging the current code and all includes into one code and this requires syntax error free code. The old output file has not been deleted before a new output file is to be created. Therefore the old output file was read in case of a failure. I have corrected this now.
AZJIO wrote: Thu Oct 13, 2022 9:21 pm4. Use \PureBasic\SDK\Syntax Highlighting\SyntaxHighlighting.dll
Unfortunately, PB does not provide such a library for the Linux version. Thanks for the code you posted here.
AZJIO wrote: Thu Oct 13, 2022 9:21 pm5. Hexadecimal numbers are not parsed correctly
Fixed.
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
AZJIO
Addict
Addict
Posts: 1360
Joined: Sun May 14, 2017 1:48 am

Re: Is it possible to find defined and unused variables?

Post by AZJIO »

Sicro
I began to receive the message often:
Your code is empty or contains syntax errors, so the PB compiler cannot preprocess the code!
At first I updated only the SearchForUnusedIdentifiers file and saw an improvement. But since there was a problem with Hex numbers, I updated the rest of the "Include" files and after that I started getting an error.

I also found an interesting tool "FindAllReferences[Win]". I already have tools that no longer fit into the monitor screen, so I made some of the items that run with the %FILE parameter through LauncherComLine (screenshot)
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: Is it possible to find defined and unused variables?

Post by Sicro »

@AZJIO

The easiest way is to download the whole code archive. This way you save downloading the individual include files and all code should work right away.

Complete archive: Download
AZJIO wrote: Mon Oct 17, 2022 9:26 am I began to receive the message often:
"Your code is empty or contains syntax errors, so the PB compiler cannot preprocess the code!"
This message is now displayed by my tool when the merged code file could not be created by the PB compiler.

Make sure you have set up the tool according to the instructions in the code below the license text in the PB IDE:
; Tool Settings:
; - Arguments: "%FILE" "%TEMPFILE"
; - Event: Menu Or Shortcut
The quotes are also important at the arguments to ensure correct processing of the file paths if they contain spaces.
AZJIO wrote: Mon Oct 17, 2022 9:26 am I also found an interesting tool "FindAllReferences[Win]".
Good find. Yes, the tool could be useful here as well.
AZJIO wrote: Mon Oct 17, 2022 9:26 am I already have tools that no longer fit into the monitor screen, so I made some of the items that run with the %FILE parameter through LauncherComLine (screenshot)
Nice.

I don't have enough time again until the weekend.
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
AZJIO
Addict
Addict
Posts: 1360
Joined: Sun May 14, 2017 1:48 am

Re: Is it possible to find defined and unused variables?

Post by AZJIO »

"%FILE" "%TEMPFILE"
yes
Try the code with 16-digit numbers above. I also tried my old ChkDskGui code.
I tried to compile x64 and x86. I downloaded both by files and archive, from this page
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: Is it possible to find defined and unused variables?

Post by Sicro »

Hello AZJIO,

you are right, the quick hexadecimal number fix was not nice and only partially worked. I have spent now more time and created a new fix.

For structures, only the structure fields are now ignored.

Please try again.
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
AZJIO
Addict
Addict
Posts: 1360
Joined: Sun May 14, 2017 1:48 am

Re: Is it possible to find defined and unused variables?

Post by AZJIO »

Same error
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: Is it possible to find defined and unused variables?

Post by Sicro »

AZJIO wrote: Wed Oct 26, 2022 2:44 amSame error
Which code did you check with the tool? Remember: the code must be compilable by the PB compiler. Code like the following, for example, will not work because it is incomplete and therefore not compilable:

Code: Select all

Mark(1)\color = $BBBBBB
Mark(2)\color = $32CEED
This code is complete and works then:

Code: Select all

Structure MarkStruc
  color.i
EndStructure

Dim Mark.MarkStruc(2)

Mark(1)\color = $BBBBBB
Mark(2)\color = $32CEED
With your ChkDSkGui code, you probably get the error message from my tool because of the WinAPI function "IsUserAdmin_()" which no longer exists. PureBasic tells me under Windows 7:
isuseradmin_() is not a function, array, list, map or macro.
I think this is also the case with you, which is why the code is not compilable with the PB compiler, but compilable is a requirement of my tool.
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
miskox
User
User
Posts: 95
Joined: Sun Aug 27, 2017 7:37 pm
Location: Slovenia

Re: Is it possible to find defined and unused variables?

Post by miskox »

Hello again!

I've been following this thread. Very nice work.

Thanks.
Saso
acreis
Enthusiast
Enthusiast
Posts: 182
Joined: Fri Jun 01, 2012 12:20 am

Re: Is it possible to find defined and unused variables?

Post by acreis »

Good morning,

I'm trying write some ide tools, but I cannot retrive the handle of PureBasic Editor Scintilla window:

Code: Select all

Val(GetEnvironmentVariable("PB_TOOL_Scintilla") ; *** always zero"
The folowing code doesn't show environment variable "PB_TOOL_Scintilla":

Code: Select all


  OpenConsole()
  If ExamineEnvironmentVariables()
    While NextEnvironmentVariable()
      PrintN(EnvironmentVariableName() + " = " + EnvironmentVariableValue())
    Wend
  EndIf
  PrintN("")
  PrintN("Press Enter to quit.")
  Input()
Any hint?
Thanks
Post Reply