Projektanalyse

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

Eingeproggt

Betreff: Projektanalyse

BeitragSa, Okt 27, 2007 19:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Servus und guten Abend!

Der Code wird für die Wenigsten nützlich sein, aber ich hab ihn heute dringend gebraucht.
Warum?
Also ich hab ein immer größer werdendes Projekt und kann grad noch die Übersicht behalten. Jetzt wollte ich mal aufräumen und unnötige Variablen rausschaffen. Nur wollte ich nicht jeder Variable extra nachrennen.

Also hab ich ein Programm gebastelt, das alle globalen (ja, leider nur die) Variablen erkennt und prüft, ob sie irgendwo Verwendung finden.
Da ich mit IDEal arbeite, hab ich den Code auf IPF-Projekte ausgelegt, hab aber auch gleich BEP-Unterstützung eingebaut (BlitzEdit-Projekte)

Der Code hat noch eine Riesenmacke, weil er einfach nicht mit kurzen Variablennamen klarkommt, aber ansonsten bin ich zufrieden. Und als Leckerli gibts Zeilenzählung mit und ohne Kommentare Smile

Wer jetzt noch nicht den Browser geschlossen hat, weil ihn mein Gequassel nicht interessiert kriegt als Belohnung den
Code: [AUSKLAPPEN]
;Projektanalyse
;--------------

;WICHTIG
;Dieses Programm wurde auf meine Bedürfnisse zurechtgeschnitten.
;Es gibt einige Dinge "des alltäglichen Leben", die nicht richtig erkannt werden!
; 1) Einfache Variablen, zB x,y,i,... werden, selbst wenn sie nie verwendet werden, nie als nicht verwendet erkannt.
;    Grund dafür: Es wird schlicht und einfach mit Instr gearbeitet, weshalb "i" in "Function" und in viiiielen
;                 anderen Wörtern drinsteckt und somit als verwendet gilt.
; 2) Es werden nur Globale Variablen erkannt und gesucht
;    Grund dafür: Locale wären mir zuviel Arbeit, da man dann die einzelnen Funktionsbereiche auch beachten müsste
; 3) Dieses Programm muss aus demselben Ordner ausgeführt werden, in dem die Projektdatei liegt
;
; --- Dieses Programm wurde nur mit einem meiner Projekte getestet, daher sind weitere Bugs durchaus möglich ---

;Dateien, die zum Projekt gehören
Type file
   Field name$
   Field size_mit,size_ohne,zeile
End Type

;Variablen, die im Code als Global definiert wurden
Type var
   Field name$
End Type

;Verschiedene Variablen für die Analyse
Local filet.file,var.var
Local txt$,file,teil1$
Local com,vorkommen
Local gessize_mit,gessize_ohne,geszeile
Local project$="meinprojekt.ipf" ; <--------------- Hier Projektnamen anpassen!!! ----------
Local Reader=ReadFile(project$)

;Es können BlitzEdit (*.bep)- und IDEal (*.ipf)-Projekte erfasst werden
If Right(project,4)=".bep" Then
   While Not Eof(Reader)
      txt$=ReadLine(Reader)
      If Instr(txt$,"<mainfile>") Then
         filet=New file
         filet\name$=Left(Right(txt$,Len(txt$)-Instr(txt$,"<mainfile>")-9),Len(txt$)-20-Instr(txt$,"<mainfile>"))
      EndIf
      If Instr(txt$,"<file>") Then
         filet=New file
         filet\name$=Left(Right(txt$,Len(txt$)-Instr(txt$,"<file>")-5),Len(txt$)-12-Instr(txt$,"<file>"))
         filet\name$=Replace(filet\name$,"\","\")
      EndIf
   Wend
ElseIf Right(project$,4)=".ipf" Then
   While Not Eof(Reader)
      txt$=ReadLine(Reader)
      If Instr(txt$,"AbsPath=") Then
         filet=New file
         filet\name$=Mid(txt$,Instr(txt$,Chr(34))+2,Instr(txt$,Chr(34),Instr(txt$,Chr(34))+1)-2-Instr(txt$,Chr(34)))
      EndIf
   Wend
EndIf

;Alle Dateien im Projekt durchsuchen
For filet=Each file
   file=ReadFile(filet\name$)
   com=0 ;Anzahl der Zeichen, die als Kommentar gelten
   
   While Not Eof(file)
      txt$=ReadLine(file)
      
      ;Codestatistiken fortsetzen
      If Left(txt,1)<>";" And txt<>"" Then filet\zeile=filet\zeile+1
      If Instr(txt,";")>0 Then
         com=com+Len(Right(txt,Len(txt)-Instr(txt,";")))
      EndIf
      
      ;Globale Variable(n) erkennen
      If Instr(txt$,"Global ")>0 And (Instr(txt$,";")>Instr(txt$,"Global ") Or Instr(txt$,";")=0) Then
         ;Kommentare und "Gobal " wegschneiden
         If Instr(txt$,";") Then txt$=Left(txt$,Instr(txt$,";")-1)
         txt$=Right(txt$,Len(txt$)-7)
         txt$=Trim(txt$)
         
         ;Wenn direkt Werte zugewiesen, dann diese wegschneiden
         teil1$=""
         While Instr(txt$,"=")
            teil1$=teil1$+Left(txt$,Instr(txt$,"=")-1)
            If Instr(txt$,",",Instr(txt$,"="))=0 Then
               txt$="" ;"Notaus", da Schleife nicht von selbst beendet wird
            Else
               txt$=Right(txt$,Len(txt$)-Instr(txt$,",",Instr(txt$,"="))+1)
            EndIf
         Wend
         If teil1<>"" Then txt$=teil1$
         
         ;Wenn mehrere Vars in einer Zeile stehen, diese trennen
         If Instr(txt$,",") Then
            While Instr(txt$,",")
               var=New var
               var\name$=Left(txt$,Instr(txt$,",")-1)
               txt$=Right(txt$,Len(txt$)-Len(var\name$)-1)
            Wend
            var=New var
            var\name$=txt$
         Else ;Oder direkt erfassen
            var.var=New var
            var\name=txt$
         EndIf
      EndIf
   Wend
   
   filet\size_ohne=FileSize(CurrentDir()+filet\name$)-com
   filet\size_mit=FileSize(CurrentDir()+filet\name$)
   gessize_ohne=gessize_ohne+filet\size_ohne
   gessize_mit=gessize_mit+filet\size_mit
   geszeile=geszeile+filet\zeile
   
   CloseFile file
Next

Local Writer=WriteFile("stats.txt")
WriteLine(Writer,"Diese Variablen werden nicht im Projekt verwendet: ")
For var=Each var
   ;Zuerst Variable nochmal "bereinigen"
   If Right(var\name$,1)="$" Or Right(var\name$,1)="%" Then var\name$=Left(var\name$,Len(var\name$)-1)
   If Instr(var\name$,".") Then
      var\name$=Left(var\name$,Instr(var\name$,".")-1)
   EndIf
   vorkommen=False
   ;Jede Variable in jeder Datei suchen
   For filet=Each file
      file=ReadFile(filet\name$)
      While Not Eof(file)
         txt$=ReadLine(file)
         If Instr(txt$,var\name$) Then
            If Instr(txt$,"Global ")=0 And (Instr(txt$,";")=0 Or Instr(txt$,";")>Instr(txt$,var\name$)) Then
               vorkommen=True
            EndIf
         EndIf
      Wend
      CloseFile file
   Next
   If vorkommen=False Then
      WriteLine(Writer,var\name$)
   EndIf
Next
WriteLine(Writer,"")
;Um die Statistiken zu schreiben, nocheinmal alle Dateien durchgehn
For filet=Each file
   WriteLine(Writer,filet\name$)
   WriteLine(Writer,"Dateigröße mit Kommentare: "+filet\size_mit)
   WriteLine(Writer,"Dateigröße ohne Kommentare: "+filet\size_ohne)
   WriteLine(Writer,"Zeilen (ohne Leer- und Kommentarzeilen): "+filet\zeile)
   WriteLine(Writer,"")
Next
WriteLine(Writer,"=========================")
WriteLine(Writer,"Gesamtgröße mit Kommentaren: "+gessize_mit)
WriteLine(Writer,"Gesamtgröße ohne Kommentaren: "+gessize_ohne)
WriteLine(Writer,"Gesamtzeilen (ohne Leer- und Kommentarzeilen): "+geszeile)
Print "Fertig. Bitte Taste drücken"
WaitKey()
End


Edit:
LOL.. gerade eben hab ich erfahren, dass es eh ne in IDEal integrierte Funktion dafür gibt... naja, ähm, macht mit dem Code was ihr wollt. Vlt lernt der eine oder andere noch Stringbearbeitung daraus Very Happy
gn8
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9

Vertex

BeitragSo, Okt 28, 2007 14:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe hier mal noch die EBNF Definition für BlitzBasic gemacht. Das ganze wird aber sicher unvollständig/fehlerhaft sein.
Code: [AUSKLAPPEN]
Comment       = ';' {Characters};
Digit         = '0' | '1' | '2' | ... | '9';
Letter        = 'A' | 'B' | 'C' | ... | 'Z'
              | 'a' | 'b' | 'c' | ... | 'z';

DecimalNumber = Digit {Digit};
BinaryNumber  = '%' BinDigit {BinDigit};
BinaryDigit   = '0' | '1';
HexNumber     = '$' HexDigit {HexDigit};
HexDigit      = Digit
              | 'A' | 'B' | 'C' | ... | 'Z'
              | 'a' | 'b' | 'c' | ... | 'z';

Number        = DecimalNumber | BinaryNumber | HexNumber;
String        = '"' {CHARACTERS} '"';
Identifier    = Letter {'_' | Letter | Digit};
Label         = '.' Identifier;
Relation      = '>' | '>=' | '=>' | '=' | '<=' | '=<' | '<' | '<>' | '><'

Gosub         = 'Gosub' Identifier;
Goto          = 'Goto' Identifier;
Include       = 'Include' String;

Variable      = Identifier ['%' | '#' | '$' | '.' Identifier];
Constant      = 'Const' Identifier ['%' | '#' | '$'] '=' Expression;
Global        = 'Global' Variable {',' Variable};
Local         = 'Local' Variable {',' Variable};
Dim           = 'Dim' Identifier
                '(' DecimalNumer {',' DecimalNumber} ')';

Factor        = (Identifier ['%' | '#' | '$' | '.' Identifier])
              | (Number | String)
              | (Identifier '(' [Expression {"," Expression}] ')')
              | '~' Factor;
              | '(' Expression ')'

Term          = Factor
              | Term '*' Factor
              | Term '/' Factor
              | Term 'Mod' Factor
              | Term 'And' Factor;

SimpleExpr    = ['+' | '-'] Term {('+' | '-' | 'Or' | 'Xor') Term};
Expression    = SimpleExpr [Relation SimpleExpr];
Statement     = Expression
              | ForNext
              | RepeatUntil
              | WhileWend
              | Condition
              | SelectCase
              | Gosub
              | Goto

ForNext       = 'For' Identifier '=' Expression 'To' Expression ['Step' Expression]
                {Statement}
                'Next';

RepeatUntil   = 'Repeat'
                {Statement}
                'Until' Expression;

WhileWend     = 'While' Expression
                {Statement}
                'Wend';

Condition     = ('If' Expression 'Then' Statement)
              | ('If' Expression 'Then'
                 {Statement | 'ElseIf' Expression 'Then'}
                 ('EndIf' | 'End If')
                );

SelectCase    = 'Select' Expression
                {'Case' Expression {Statement}}
                ['Default' Expression {Statement}]
                {'Case' Expression {Statement}}
                ('EndSelect' | 'End Select');

Parameter     = Identifier ['%' | '#' | '$' | '.' Identifier] ['=' Expression]
Function      = 'Function' Identifier ['%' | '#' | '$' | '.' Identifier]
                '(' [Parameter {',' Parameter}] ')'
                {Local}
                {Statement}
                {Local}
                ('EndFunction' | 'End Function');

Field         = 'Field' Identifier ['%' | '#' | '$' | '.' Identifier];
Type          = 'Type' {Field} 'End Type';

Program       = {{Statement}
              |  Include
              |  Global
              |  Local
              |  Dim
              |  Constant
              |  Type
              |  Function
              |  (Label {Statement} [Return])
              |  {Statement}
                }


Daraus könnte man dann einen Lexer und Scanner entwickeln, um solche Codeanalyse ggf. Compiler zu entwickeln.

mfg olli
vertex.dreamfall.at | GitHub

panky

BeitragMo, Dez 17, 2007 13:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:

Grund dafür: Es wird schlicht und einfach mit Instr gearbeitet, weshalb "i" in "Function" und in viiiielen anderen Wörtern drinsteckt.


Das stimmt natürlich, aber ich würde einfach die Gebiete um "i" mit einbeziehen. So ist ein "freistehendes i" (das heisst mit einer Leerzeile vor und hinter dem "i") ganz sicher eine Variable. Auch ein "," vor und hinter dem "i" weist auf eine Variable hin.

Eingeproggt

BeitragMo, Dez 17, 2007 14:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, das wäre aufwendig. Natürlich irgendwie zu machen. Bei solchen Fällen wirds aber kompliziert:

Code: [AUSKLAPPEN]
i=1+i


Vlt ein etwas dumes Beispiel, aber es soll zeigen, dass man auf alle Operatoren, nicht nur Leerzeichen und "," überpüfen müsste.

Aber ich hab jetzt die IDEal-Funktion "Review Declarations" gefunden. Die erfüllt meine Bedürfnisse weit besser als dieser Code Smile
(Danke nochmal an denjenigen, der mich darauf hinwies, auch wenn ich vergessen hab, wer es war...)

mfG, Christoph.
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group