Ungenutzte Variablen ermitteln

    • Offizieller Beitrag

    Jeder wird es kennen, ein Skript wächst und wächst. Variablen werden deklariert und manchmal auch entfernt. Und zum Schluß weiß man gar nicht, ob alle deklarierten auch verwendet werden.
    Mit diesem Skript könnt ihr:
    - einmalig genutze Variablen (Standard) oder
    - alle verwendeten Variablen ausgeben lassen
    Die Ausgabe enthält:
    - Funktionsbereich (Funktionsname für Variablen in Funktionen, sonst 'Out_Of_Func')
    - Variablenname
    - Anzahl Vorkommen
    - Zeile(n) des Vorkommens
    Die Ausgabe erfolgt als:
    - String in die Konsole (Standard)
    - Array

    Ignoriert werden Variablen in Kommentarzeilen/-blöcken und ebenso Zählervariablen in For-Schleifen.

    Ich prüfe (noch) nicht gegen includierte Konstanten, sodass diese bei einmaliger Verwendung auch als 'ungenutzt' erscheinen. Diese Prüfung werde ich später noch einbauen. Im Moment testet mal, ob es bei diversen Skripten auch funktioniert.
    Es gibt eine bekannte Konstellation, in der ein Kommentar nicht erkannt wird:
    Bsp:

    [autoit]

    $sVariable = 'irgendwas;' ; Kommentar dazu und dieselben 'Stringbegrenzer', wie in der Zuweisung, $sVariable enthält beliebigen String

    [/autoit]

    In dieser Zeile kann der Kommentar nicht lokalisiert werden, da das letzte Semikolon als Stringbestandteil interpretiert wird: ' ; Kommentar dazu und dieselben ' und somit der Variablenname im Kommentar mitgezählt wird. Da dieser Fall sicher sehr unwahrscheinlich ist sehe ich das aber als unkritisch an.

    Die Array-Ausgabe sieht z.B. so aus
    autoit.de/wcf/attachment/13135/

    Am einfachsten die Funktion in das SciTE-Menü einbinden "SciTEUser.properties"
    # END => DO NOT CHANGE ANYTHING BEFORE THIS LINE #-#-#-#-#-#
    # 39 Unused Vars
    command.39.*.au3="$(autoit3dir)\autoit3.exe" "$(SciteDefaultHome)\GetUnusedVars.au3" "$(FilePath)" "1" "0"
    command.name.39.*.au3=GetUnusedVars
    command.save.before.39.*.au3=1
    command.is.filter.39.*.au3=1
    command.shortcut.39.*.au3=Ctrl+Shift+Alt+U
    Den Shortcut könnt ihr natürlich anpassen, ebenso, wie den Pfad zur Datei.

    Die Aufrufzeile enthält zwei optionale Parameter, hier: "1" "0"
    Diese stehen für
    Alle-Variablen: "0" (Standard, einmalig) oder "1" (alle Vorkommen) und
    Ausgabe: "1" (Standard, in Konsole) oder "0" (als Array)

    Edit: Kleiner 'Guttenberg-Error' :D (gefixt)

    Hier der Code:

    GetUnusedVars.au3
    [autoit]

    #include-once
    #include <File.au3>
    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    If $CmdLine[0] Then
    Local $sFile = $CmdLine[1], $fAll = 0, $fString = 1
    Switch $CmdLine[0]
    Case 3
    $fAll = $CmdLine[2]
    $fString = $CmdLine[3]
    Case 2
    $fAll = $CmdLine[2]
    EndSwitch
    Else
    Exit
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite('+>' & @HOUR & ':' & @MIN & ':' & @SEC & ' Start: Get_Unused_Vars' & @CRLF)
    Local $vReturn = _GetUnusedVarsConst($sFile, $fAll, $fString)
    Local $error = @error
    ConsoleWrite('+>' & @HOUR & ':' & @MIN & ':' & @SEC & ' Ende: Get_Unused_Vars' & @CRLF)
    If @error Then ConsoleWrite('!Fehler: Datei "' & $sFile & ' existiert nicht.' & @CRLF)
    If $fString = 0 Then
    _ArrayDisplay($vReturn)
    Else
    ConsoleWrite($vReturn & @CRLF)
    EndIf

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ; Function Name: _GetUnusedVarsConst
    ; Description: Ermittelt ungenutzte Variablen/Konstanten in einem Skript
    ; Optional können alle Variablen mit Anzahl der Vorkommen ermittelt werden
    ; Ignoriert werden:
    ; Variablen in Kommentarzeilen
    ; Variablen in Kommentarblöcken
    ; Zählervariablen (For-Schleife)
    ; Parameter(s): $sFile Pfad zur Skriptdatei
    ; $fAll 1 - Rückgabe aller Variablen; 0(Standard) - einmalige Variablen
    ; $fString 1(Standard) - Rückgabe in Konsole; 0 - Anzeige Array
    ; Return Value(s): Erfolg Standard Array/String mit nur einmalig auftauchender Variable
    ; Optional Array/String mit allen Variablen
    ; Ausgabe: Funktionsbereich - Variable - Anzahl - Position:Zeile(n)
    ; Fehler 0 @error = 1 $sFile nicht vorhanden
    ; Author(s): BugFix ([email='bugfix@autoit.de'][/email])
    ;===============================================================================
    Func _GetUnusedVarsConst($sFile, $fAll=0, $fString=1)
    Local $oVars = ObjCreate('Scripting.Dictionary')
    Local $oFuncVars = ObjCreate('Scripting.Dictionary')
    Local $aFuncs[1][2] = [[0]] ; [['Funktionsname','var1/Anz1/Zeile(1.),Zeile(2.)..' & '|' & 'var1/Anz1/Zeile(1.),Zeile(2.)..' & '|' & 'var(n)/Anz(n)/Zeile(1.),Zeile(2.)..' ]]
    Local $aFile, $tmp, $aSplit, $aMatch, $inFunc = False, $counterFor = '', $1stChar, $iPos, $sSign, $fSet, $iSemicolon, $skip, $sFuncName
    If Not FileExists($sFile) Then Return SetError(1,0,0)
    _FileReadToArray($sFile, $aFile)
    For $i = 1 To $aFile[0]
    ; Kommentarblöcke werden übersprungen
    ; auskommentierte Zeilen werden übersprungen
    $1stChar = StringLeft(StringStripWS($aFile[$i],1), 1)
    If $1stChar = ';' Then ContinueLoop
    If (StringInStr($aFile[$i], '#cs') Or StringInStr($aFile[$i], '#comments-start')) Then $skip = True
    If (StringInStr($aFile[$i], '#ce') Or StringInStr($aFile[$i], '#comments-end')) Then $skip = False
    If $skip Then ContinueLoop
    Select
    Case StringLeft(StringStripWS($aFile[$i], 1), 4) = 'Func'
    ; Beginn Funktionscode
    ; Funktionsnamen auslesen u. in Func-Array eintragen
    ; Funktionszähler +1
    $inFunc = True
    $aMatch = StringRegExp($aFile[$i], '^(?:[F|f]unc\s+)([_a-zA-Z0-9]+)', 1)
    $sFuncName = $aMatch[0]
    ; Variablen aus Funktionsheader (auch mehrzeilig) auslesen und in $oFuncVars erfassen
    ; steht eine Variable in einem Kommentar hinter dem Header wird sie ignoriert
    $aMatch = StringRegExp($aFile[$i], '(?:[F|f]unc\s+[\d\w]+\()[$,\w\s]*(?:\)?)', 1) ; Codeteil vor mgl. Kommentar oder '_'
    $aMatch = StringRegExp($aMatch[0], '(\$[\d\w]+)', 3)
    If IsArray($aMatch) Then __VarObjectAdd($oFuncVars, $aMatch, $counterFor, $i)
    Case StringLeft(StringStripWS($aFile[$i], 1), 7) = 'EndFunc'
    ; Ende Funktionscode
    ; in $oFuncVars gesammelte Variablen/Anzahl in $aFuncs übertragen
    ; optional ($fAll=True) werden alle Variablen mit Anzahl Vorkommen übertragen
    ; standardmäßig nur Variablen mit einmaligem Vorkommen
    If $oFuncVars.Count Then
    __SetToFuncArray($aFuncs, $oFuncVars, $fAll, $sFuncName)
    $oFuncVars.RemoveAll
    EndIf
    $inFunc = False
    Case Else ; Codezeilen innerhalb oder außerhalb einer Funktion, durch $inFunc markiert
    ; prüfen auf For-Schleife, Selektion Zählervariable
    If StringLeft(StringStripWS($aFile[$i], 1), 3) = 'For' Then
    $aMatch = StringRegExp($aFile[$i], '(?:[F|f]or\s+)(\$[\d\w]+)', 1)
    $counterFor = $aMatch[0]
    EndIf
    ; prüfen auf Ende For-Schleife, Zurücksetzen Zählervariable, nächste Zeile
    If StringLeft(StringStripWS($aFile[$i], 1), 4) = 'Next' Then
    $counterFor = ''
    ContinueLoop
    EndIf
    ; prüfen ob ';' enthalten und wieviel
    StringReplace($aFile[$i], ';', '')
    $iSemicolon = @extended
    $fSet = False
    If $iSemicolon Then
    ; Anzahl der ';' gibt keine Auskunft ob Kommentar od. Wertzuweisung
    ; wenn Wertzuweisung, muß vor und nach dem ; ein ' oder " sein (Stringbegrenzer)
    ; ist eines der Zeichen enthalten könnte es eine Wertzuweisung sein
    ; es braucht nur das letzte Vorkommen geprüft werden, wenn nicht in Stringbegrenzern ist es Kommentar
    ; wenn Kommentar - diesen Teil abtrennen
    ; ABER: wenn letzter Stringbegrenzer vor Semikolon == mit einem Stringbegrenzer im Kommentar ==> Kommentar wird nicht erkannt!
    If StringInStr($aFile[$i], '"') Or StringInStr($aFile[$i], "'") Then ; sind Stringbegrenzer vorhanden
    $sSign = ''
    $iPos = StringInStr($aFile[$i], ';', 1, -1) ; letztes Vorkommen ermitteln
    $aSplit = StringSplit($aFile[$i], '')
    For $j = $iPos -1 To 1 Step -1 ; rückwärts iterieren ab Semikolon
    If $aSplit[$j] = '"' Or $aSplit[$j] = "'" Then
    $sSign = $aSplit[$j]
    ExitLoop
    EndIf
    Next
    ; wenn Stringbegrenzer links gefunden
    If $sSign <> '' Then ; vorwärts iterieren ab Semikolon
    For $j = $iPos +1 To $aSplit[0]
    If $aSplit[$j] = $sSign Then ; davor und danach dasselbe ' od. " ==> also Zuweisung
    $fSet = True
    ExitLoop
    EndIf
    Next
    EndIf
    EndIf
    If Not $fSet Then ; ist Kommentar, nicht Zuweisung
    $aFile[$i] = StringLeft($aFile[$i], StringInStr($aFile[$i], ';', 1, -1) -1)
    EndIf
    EndIf
    ; Variablen selektieren und an $oFuncVars oder $oVars übergeben
    $aMatch = StringRegExp($aFile[$i], '(\$[\d\w]+)', 3)
    If IsArray($aMatch) Then
    If $inFunc = True Then
    __VarObjectAdd($oFuncVars, $aMatch, $counterFor, $i)
    Else
    __VarObjectAdd($oVars, $aMatch, $counterFor, $i)
    EndIf
    EndIf
    EndSelect
    Next
    If $oVars.Count Then __SetToFuncArray($aFuncs, $oVars, $fAll)
    Local $aRet[1][4] = [['Funktionsbereich','Variable','Anzahl','Zeile(n)']], $aSplit2, $sRet = 'Funktionsbereich - Variable - Anzahl - Zeile(n)' & @CRLF
    For $i = 1 To UBound($aFuncs) -1
    $aSplit = StringSplit($aFuncs[$i][1], '|')
    For $j = 1 To $aSplit[0]
    $aSplit2 = StringSplit($aSplit[$j], '/')
    If @error Then ContinueLoop
    $sRet &= $aFuncs[$i][0] & ' - ' & $aSplit2[1] & ' - ' & $aSplit2[2] & ' - ' & $aSplit2[3] & @CRLF
    If $fString = 0 Then
    ReDim $aRet[UBound($aRet)+1][4]
    $aRet[UBound($aRet)-1][0] = $aFuncs[$i][0]
    $aRet[UBound($aRet)-1][1] = $aSplit2[1]
    $aRet[UBound($aRet)-1][2] = $aSplit2[2]
    $aRet[UBound($aRet)-1][3] = $aSplit2[3]
    EndIf
    Next
    Next
    If $fString = 0 Then Return $aRet
    Return $sRet
    EndFunc ;==>_GetUnusedVarsConst

    [/autoit] [autoit][/autoit] [autoit]

    Func __VarObjectAdd(ByRef $oDict, $aMatch, $counterFor, $line)
    Local $aSplit
    For $i = 0 To UBound($aMatch) -1
    If $aMatch[$i] = $counterFor Then ContinueLoop ; Zählervariablen werden nicht gezählt
    If $oDict.Exists($aMatch[$i]) Then
    $aSplit = StringSplit($oDict.Item($aMatch[$i]), '/')
    $oDict.Item($aMatch[$i]) = $aSplit[1] +1 & '/' & $aSplit[2] & ',' & $line
    Else
    $oDict.Add($aMatch[$i], 1 & '/' & $line)
    EndIf
    Next
    EndFunc ;==>__VarObjectAdd

    [/autoit] [autoit][/autoit] [autoit]

    Func __SetToFuncArray(ByRef $aFuncs, ByRef $oDict, $fAll, $sFuncName='')
    Local $aSplit, $colKeys, $sVarCount = ''
    $colKeys = $oDict.Keys
    For $key In $colKeys
    If $sFuncName <> '' Then
    ReDim $aFuncs[UBound($aFuncs)+1][2]
    $aFuncs[UBound($aFuncs)-1][0] = $sFuncName
    EndIf
    If $fAll = 0 Then
    If Not StringRegExp($oDict.Item($key), '(1/\d+)') Then ContinueLoop
    EndIf
    $aSplit = StringSplit($oDict.Item($key), '/')
    $sVarCount &= $key & '/' & $aSplit[1] & '/' & $aSplit[2] & '|'
    If $sFuncName <> '' Then
    $aFuncs[UBound($aFuncs)-1][1] = StringTrimRight($sVarCount, 1)
    $sVarCount = ''
    EndIf
    Next
    If $sFuncName = '' Then
    ReDim $aFuncs[UBound($aFuncs)+1][2]
    $aFuncs[UBound($aFuncs)-1][0] = 'Out_Of_Func'
    $aFuncs[UBound($aFuncs)-1][1] = StringTrimRight($sVarCount, 1)
    EndIf
    EndFunc ;==>__SetToFuncArray

    [/autoit]

    ToDoList:
    - auf includierte Konstanten prüfen
    - auf includierte Globale Variablen prüfen
    - Globale Variablen gegen Variablen in Funktionen abgleichen

  • Schöne Idee. Ich hätte hier eine funktionierende Lösung, um Die Kommentare besser zu parsen ;)

    [autoit]

    #include<Array.au3>

    [/autoit][autoit][/autoit][autoit]

    $sString = " $sVariable = 'irgendwas;' ; Kommentar dazu und dieselben 'Stringbegrenzer', wie in der Zuweisung, $sVariable enthält beliebigen String"
    $a = StringRegExp($sString, "^\h*(\$\S+)\h*([-+*/&]?=)\h*((?:[^;'""]+|(['""])(?:[^\4]|\4\4)*?\4(?!\4))+)\h*(;?.*)$", 1)
    _ArrayDisplay($a)

    [/autoit]

    Wenn man nur Befehl und Kommentar trennen will, ist es so ausreichend:

    [autoit]

    $a = StringRegExp($sString, "^\h*((?:[^;'""]+|(['""])(?:[^\2]|\2\2)*?\2(?!\2))*)\h*(;?.*)$", 1)
    ; [0] ist Befehl, [1] der letzte gefundene Stringbegrenzer, [2] der Kommentar
    _ArrayDisplay($a)

    [/autoit]
    • Offizieller Beitrag

    wohin muss die GetUnusedVars.au3 kopiert werden

    $(SciteDefaultHome) ist das Installationsverzeichnis von SciTE. Das würde ich nicht zum Speichern eigener Anwendungen empfehlen. Verwende besser einen Ordner im Bereich USER, indem du Skripte (au3 und lua) für SciTE ablegst. Z.B. C:\Users\USER\MySciTE.

    Am Besten speicherst du diesen Pfad in der SciTEUser.properties (SciTE-Optionen-Benutzereinstellungen) als:

    User.Scripts.Path=C:\Users\USER\MySciTE

    Dann kannst du später in den SciTE.properties auf den Pfad immer zugreifen in der Form $(User.Scripts.Path).

    In deinem Fall also entweder:

    command.39.*.au3="$(autoit3dir)\autoit3.exe" "C:\Users\USER\MySciTE\GetUnusedVars.au3" "$(FilePath)" "1" "0"

    oder:

    command.39.*.au3="$(autoit3dir)\autoit3.exe" "$(User.Scripts.Path)\GetUnusedVars.au3" "$(FilePath)" "1" "0"

  • Hallo BugFix,

    wie gut sieht es mit der geplanten Nutzung von Variablendeklarationen in Include Dateien aus?

    Bei mir habe ich dein Script mal auf ein (zugegebenermassen extrem umfangreiches) Projekt angesetzt und es gibt Variablen aus als 'Out_Of_Func' aus die in einer geschachtelten include Ebene enthalten sind. Bei dem Projekt sind die Variablen nicht in der Hauptroutine deklariert, sondern die Dekalaration erfolgt über eine include Datei die die Variablendeklaration enthält. Um es noch komplizierter zu machen, gibt es für die Internationalisierung der GUI auch Include-dateien in zweiter Schachtelungsebene (komme nicht dazu die Meldungen in eine ini-Datei zu verfrachten). Schachtelung ist also etwa in der Form Hauptcode => Include Globale Variablendeklaration => Include Internationale GUI-Meldung . Bin mir jetzt nicht sicher, ob eine solche Stuktur bei der Überprüfung überhaupt vorgesehen war.

    Bei normalen Skripten ohne Variablendeklaration in Include-Dateien funktioniert es bei mir prima.

    Danke PapaPeter

    Mit freundlichen Grüßen - PapaPeter

    • Offizieller Beitrag

    wie gut sieht es mit der geplanten Nutzung von Variablendeklarationen in Include Dateien aus?

    Kennst du vielleicht: Bei der Entwicklung des Skriptes fällt dir auf, dass sich noch ein ständig wachsender Haufen an Folgemaßnahmen erforderlich macht und dann schiebst du das erst mal vor dir her. :whistling: Ein wesentlicher Punkt (der mich auch bei meinem ManageIncludes gebremst hat) ist eine Routine zum rekursiven Auslesen/Vergleichen der Includes. Da habe ich schon etliche Ansätze probiert aber noch nichts (geschwindigkeitsmäßig) zufriedenstellendes gefunden. Dadurch dass viele Includes Querverweise auf andere Includes haben, landet man da schnell in einem InfinityLoop. <X

    Ich werde vermutlich das Parsen der Includes in ein externes (Nicht-AutoIt) Programm auslagern, das mit der notwendigen Geschwindigkeit arbeitet.

    Bei dem Projekt sind die Variablen nicht in der Hauptroutine deklariert, sondern die Dekalaration erfolgt über eine include Datei die die Variablendeklaration enthält. Um es noch komplizierter zu machen, gibt es für die Internationalisierung der GUI auch Include-dateien in zweiter Schachtelungsebene

    He, da ticken wir ähnlich. ;)

    In meinen (größeren) Projekten baue ich das so auf:

    - Mainskript (meist nur ein paar Zeilen: Includes, Initialisierungsaufrufe(Variablen, GUI), Mainloop)

    - getrennte Includes: Variablendeklaration, Variableninitialisierung, GUI-Erstellung, GUI-Funktionen, Programmfunktionen

    Aber ich halte das alles in einer Ebene.

    Bei derartigen Konstrukten ist das Problem, dass ein Include auf Variablen zugreift, welche in einem anderen Include deklariert sind, aber dieses Include noch nicht geparst wurde.

    Hier die richtigen Abhängigkeiten zu finden ist nicht ohne. Eigentlich müsste man dasselbe tun, wie der Interpreter: Alle Includes in einen gemeinsamen Kontext zusammenführen und dann parsen.

    Aber, wie schon oben beschrieben, wird eine Lösung für ManageIncludes auch hier ein bessere Umsetzung ermöglichen.

  • Da gebe ich Dir vollkommen recht, eine gute Idee zieht manchmal viel nach was dann ach noch alles berücksichtigt werden kann und das man im ersten Anlauf gar nicht gesehen hat.

    Wenn Du dich durch alle Dateien hangeln willst, würde ich folgendermassen vorgehen - aber das wäre nur mein Ansatz:
    Starte mit dem ursprünglichen Script arbeite dich Zeile für Zeile durch das Skript und kopiere den gescannten Teil eine Tempdatei.
    Sobald Du auf ein Include triffst - trage es in eine Liste ein. Wenn das Include vorher schon in der Liste war überspringe es, Wenn das Include vorher nicht in der Liste war, arbeite das Include jetzt analog zeilenweise ab, bis Du auf das nächste include triffst oder oder das Ende des includes erreichst.
    Hast Du das Ende des Includes erreicht mache mit dem Sourcecode in der übergeordneten Ende weiter bis du irgendwann das Ende der Haupdatei erreicht hast.
    Am Ende hast Du eine temporäre Datei die allen Sourcecode einmal in chronlogischer Reihenfolge enthält und den du dann parsen kannst.

    Include-Once würde ich ignorieren und Includes auch nicht mehr mehrfach einbinden (wegen der Gefahr von Schleifen).
    Das einzige Problem was Du jetzt noch hast ist die Zuordnung der Zeilen in der Tempdatei zu den eigentlichen Sourcecodedateien.

    Hier fallen mir zwei Ansätze ein, entweder Du führst eine Liste die Zuordnung jeder Zeile in der Tempdatei zu der Zeile und den Namen der Sourcecodedatei enthält (u.U. schneller aber Resoucen fressender) oder du erfasst nur eine Liste der Sprünge zwischen den Soucecodedateien mit jeweiligenj Zeilennummern (weniger Resourcen, aber schwieriger zu tracken). Diese Hilfslisten sollten sich auch parallel auch dazu nutzen zu lassen, wo man am Ende des Parsen einer Sourcecodedatei weiterfortsetzen muss.

    Am Ende musst Du also sogar noch mehr tun als der Interpreter, da es ja nicht reicht einen Fehler festzustellen, sondern man muß ihn ja auch noch lokalisieren.

    Die Umsetzung könnte ein interessante Herausforderung werden, aber fürchte Dir bleibt dazu vermutlich genauso wenig Zeit wie mir.
    Wenn ich in näherer Zeit (Sommerferien vielleicht) etwas Luft haben sollte und Du auch noch Unterstüzung möchtest, könnte ich Dich gerne unterstützen. Aber ich verstehe auch wenn das Du gerne das Heft in der Hand halten möchtest und Programmierstile sind auch nicht immer kompatibel. Sehe es einfach als Angebot das Du auch unbegründet ablehnen kannst - ich bin Dir in keinem Fall böse.

    PapaPeter

    Mit freundlichen Grüßen - PapaPeter

  • Zitat

    In meinen (größeren) Projekten baue ich das so auf:

    - Mainskript (meist nur ein paar Zeilen: Includes, Initialisierungsaufrufe(Variablen, GUI), Mainloop)

    - getrennte Includes: Variablendeklaration, Variableninitialisierung, GUI-Erstellung, GUI-Funktionen, Programmfunktionen

    Aber ich halte das alles in einer Ebene.

    Das ist bei mir ähnlich kurzes Hauptprogramm, das dann die Haupbestandteile also aufruft, also:
    * Globale Variablen und Allgemeine Autoit Includes (hier oder nach der Initialisierung ggf. Einbindung von länderspezifischen Parameter für Internationalisierung als getrenntes Include)

    * Programmspezifische Funktionsbibliotheken als includes definiert
    * Includes für die Initialisierung (Parameter aus SQL Datenbanken oder ini-dateien einlesen), ggf. auch Auto-Update des kompilierten Programms
    * Funktionen für die GUI (deren oberste Ebene) aus dem Hauptprogramm aufgerufen werden,

    * Include für das Gui-Handling und die Auswertung der Gui und zwar die Teile die nicht direkt aus dem Hauptprogramm aufgerufen werden. Gegebenfalls - je nach Umfang - noch getrennt wie es thematisch passt.

    Manchmal kann - zumindestens ich - es ablauftechnisch aufgrund der Deklarations-Abhängigkeiten nicht vermeiden die Includes zu schachteln, andererseits versuche ich halt thematische Blöcke pro include zu finden um sich nicht einen Wolf bein Debugging zu suchen.

    In meinen größten Projekt stecken einige 10.000 Zeilen eigener Code. Deshalb dokumentiere und modularisiere ich lieber extrem, als Code auf Teufel komm raus zu optimieren, Schliesslich will ich einen Fehler auch noch 3 Jahre später finden können, nur weil ich gerade mal was angepasst habe und jetzt der Fehler nicht auf Anhieb zu finden ist sondern durch die andere Nutzung ganz wo anders vergraben ist.

    PapaPeter

    Mit freundlichen Grüßen - PapaPeter

  • Hallo Bugfix,

    Wenn ich noch genauer nachdenke fallen 2 Dinge ein die ich noch variieren würde:

    Zitat

    ... Sobald Du auf ein Include triffst - trage es in eine Liste ein. Wenn das Include vorher schon in der Liste war überspringe es, Wenn das Include vorher nicht in der Liste war, arbeite das Include jetzt analog zeilenweise ab, bis Du auf das nächste Include triffst oder oder das Ende des Includes erreichst....

    Da man in der Regel nicht an "unnötig" deklarierten Variablen/Konstanten in Standard-Includes interessiert ist und um diese nicht jedes Mal durchsuchen zu müssen, würde ich eine Option vorsehen diese zu ignorieren. In dem Fall würde das Include einfach so übernommen, wie es im Sourcecode steht.

    Eine weitere Variation wurde ich ebenfalls [optional] noch in diesem Punktt vornehmen:

    Zitat

    ... Starte mit dem ursprünglichen Script arbeite dich Zeile für Zeile durch das Skript und kopiere den gescannten Teil eine Tempdatei....

    Im Sinne einer schnelleren Abarbeitung und in Anbetracht heutiger Speichergrößen, sollte es in der Regel reichen das Ergebnis in ein Array zu schreiben.

    Papa Peter

    Mit freundlichen Grüßen - PapaPeter

    • Offizieller Beitrag

    PapaPeter

    Dein letzter Post war 4:20 Uhr ?! - Und was machst du tagsüber? :rofl:

    Danke für deine Gedanken und das Hilfsangebot.

    Momentan erledige ich erstmal einiges "drumherum". Da ich die ManageIncludes endlich fertigstellen will schreibe ich mir erst mal externe Parser, in der Hoffnung dann auf das Abspeichern von Funktionen/Konstanten etc. verzichten zu können und tatsächlich On-The-Fly zu arbeiten. Mal sehen ob das performancemäßig möglich ist. Wird evtl. davon abhängen, wie ich IPC hier umsetzen kann.

    Ggf. werde ich dann auf dein Angebot zurückkommen.

    Und jetzt geh erst mal schlafen. :P

  • Und was machst du tagsüber?

    Im Augenblick machen wir in unserem Betrieb Schichtdienst - wegen Coronna und Reduzierungs des Ansteckungsrisiko. Auch wenn ich viel von zuhause arbeiten kann, muß ich dann auch in dem entsprechenden Zeitschema arbeiten.

    Durch die Schichtwechsel ist der Schlafrythmus immer etwas gestört, das wäre die Zeit wo ich für die Frühschicht aufstehen müßte - auch wenn ich diese Woche Spätschicht habe.

    PapaPeter

    Mit freundlichen Grüßen - PapaPeter

    Einmal editiert, zuletzt von PapaPeter (20. Mai 2020 um 16:52)