Sign in Join
Wiki copytemporary

Codetools/de

Deutsch · English · Français · Русский

Was sind die CodeTools

Die CodeTools sind ein Lazarus-Package mit Werkzeugen zum Parsen, Untersuchen, Bearbeiten und Refaktorieren von Pascal-Quelltexten. Die CodeTools sind ein Modul für sich und unter der GPL lizensiert. Zahlreiche Beispiele, wie Sie die CodeTools in Ihren eigenen Programmen einsetzen können, finden Sie unter 'components/codetools/examples'.

svn:

Verwendung der CodeTools ohne die IDE (gut für Testzwecke)

Sie können die CodeTools ohne die IDE verwenden. Dies kann zum Testen eines neuen Werkzeugs genutzt werden. Ein einfaches Beispiel ist

text
 <lazarusdir>/components/codetools/examples/methodjumping.lpi

Um die find declaration zu testen, müssen die CodeTools die Quellen analysieren, besonders die RTL- und FCL-Quellen. Die Beispiele benutzen folgende Umgebungsvariablen:

FPC ist ein sehr komplexes Projekt mit vielen Suchpfaden, Include-Dateien und Makros. Die CodeTools müssen alle diese Pfade und Makros kennen, um diesen Dschungel zu analysieren. Um dies alles einfach einzurichten, enthalten die CodeTools vordefinierte Schablonen für FPC-, Lazarus-, Delphi- und Kylix-Quellverzeichnisse. Betrachten Sie für ein find declaration folgendes Beispiel

text
 <lazarusdir>/components/codetools/examples/finddeclaration.lpi

Weil die FPC-Quellen mehrere Versionen einiger Units enthalten und die FPC-Quellen oft geändert werden, verwenden die CodeTools keine starre Pfadtabelle. Stattdessen scannen sie zuerst die gesamte FPC Verzeichnisstruktur und versuchen mittels einiger Regeln herauszufinden, welche Quelle die richtige ist für das gegenwärtige ZielOS und ZielCPU. Dieser Scan kann eine Weile dauern. Alle Beipiele speichern das Ergebnis in codetools.config, damit diese Suche beim nächsten Start übersprungen wird.

Wann immer die FPC-Quellen verschoben wurden oder eine Unit umbenannt wurde, löschen Sie einfach die Datei codetools.config. Die Lazarus-IDE hat ihre eigene Konfigurationsdatei und erledigt den Rescan, wann immer das Compiler executable geändert wurde oder der Benutzer dies erzwingt mit 'Einstellungen > FPC-Quelltextverzeichnis neu einlesen'.

Verwendung der CodeTools in der IDE mit dem IDEIntf

Siehe das <lazarusdir>/examples/idequickfix/quickfixexample.lpk Package. Es demonstriert:

Codetools-Regeln für FPC-Quelltexte

Wenn die CodeTools die Quelltexte nach einer FPC ppu-Datei durchsuchen, verwenden sie einen Satz von Regeln. Sie können Ihre eigenen Regeln Schreiben, aber normalerweise werden Sie die Standardregeln benutzen, die in der der Includedatei 'components/codetools/fpcsrcrules.inc' festgelegt sind. Sie können die Regeln testen mit dem Befehlszeilenwerkzeug: components/codetools/examples/testfpcsrcunitrules.lpi.

Gebrauch von testfpcsrcunitrules

pascal
Gebrauch: lazarus/components/codetools/examples/testfpcsrcunitrules -h
pascal
-c <compiler file name>, --compiler=<compiler file name>
       Vorgabe ist es, die Umgebungsvariable PP zu benutzen.
       Wenn nicht angegeben, suche nach fpc
pascal
-T <target OS>, --targetos=<target OS>
       Vorgabe ist es, die Umgebungsvariable FPCTARGET zu benutzen.
       Wenn nicht angegeben, nimm die Vorgabe des Kompilers.
pascal
-P <target CPU>, --targetcpu=<target CPU>
       Vorgabe ist es, die Umgebungsvariable FPCTARGETCPU zu benutzen.
       Wenn nicht angegeben, nimm die Vorgabe des Kompilers.
pascal
-F <FPC source directory>, --fpcsrcdir=<FPC source directory>
       Vorgabe ist es, die Umgebungsvariable FPCDIR zu benutzen.
       Es gibt keine andere Vorgabe.
pascal
-u <unit name>, --checkunit=<unit name>
       Schreibe einen detailierten Bericht ??ber diese Unit.

Beispiel für testfpcsrcunitrules

Öffnen Sie die Datei 'testfpcsrcunitrules.lpi' in der IDE und kompilieren Sie sie. Starten Sie dann das Werkzeug in einer Befehlszeile/Konsole:

text
./testfpcsrcunitrules -F ~/fpc/sources/2.5.1/fpc/

Dadurch erfahren Sie, welcher Kompiler benutzt wird, welcher Kompiler ausgeführt wird, welche Konfigurationsdateinen getestet und analysiert wurden, Sie werden gewarnt über doppelte Units im FPC-Suchpfad und doppelte Quelltextdateien für die selbe Unit.

Doppelte Quelltextdateien

Angenommen, Sie finden heraus, dass die CodeTools für das Ziel 'wince/arm' den falschen Quelltext der Unit mmsystem öffnen. Starten Sie das Werkzeug mit dem Parameter '-u':

./testfpcsrcunitrules -F ~/fpc/2.5.1/fpc/ -T wince -P arm -u mmsystem

Dadurch erhalten Sie einen detaillierten Bericht darüber, wo diese Unit gefunden wurde und welches Score jede Quelltextdatei erzielt hat. Zum Beispiel:

pascal
Unit report for mmsystem
  WARNING: mmsystem is not in PPU search path
GatherUnitsInFPCSources UnitName=mmsystem File=packages/winunits-base/src/mmsystem.pp Score=11
GatherUnitsInFPCSources UnitName=mmsystem File=packages/winceunits/src/mmsystem.pp Score=11 => duplicate

Dies bedeutet, dass es zwei Quelltextdateien mit dem selben Score gibt, sodass die CodeTools die erste genommen haben. Die letzte im Verzeichnis 'winceunits' ist für das Ziel 'wince' und die erste ist für 'win32' und 'win64'.

Öffnen Sie jetzt die Regeldatei 'fpcsrcrules.inc'.

Regeln arbeiten so:

pascal
Score:=10;
Targets:='wince';
Add('packages/winceunits');

Das Add fügt eine Regel hinzu für alle Dateien, die mit 'packages/winceunits' beginnen. Zum Score all dieser Dateien wird 10 addiert. Targets ist eine durch Kommas getrennte Liste von Zielbetriebssystemen und/oder Zielprozessoren. Beispielsweise: Targets='wince,linux,i386' bedeutet: wende diese Regel auf das ZielOS 'wince' oder 'linux' und auf die ZielCPU i386 an.

Wie die CodeTools Quelltexte untersuchen, abhängig von einem Kompiler

Ein Kompiler ist dazu optimiert den Code linear zu durchlaufen und die benötigten Units und Includedateien dann zu laden, wenn er einen uses-Abschnitt oder eine Direktive findet. Die CodeTools sind dazu optimiert, nur Teile des Codes zu untersuchen. Beispielsweise braucht der Sprung von einer Methodendeklaration zum Methodenrumpf nur die Unit und ihre Includedateien. Wenn die CodeTools eine Deklaration suchen, dann suchen sie rückwärts. Das bedeutet, sie starten die Suche in den lokalen Variablen und dann oberhalb in der Implementation. Wenn sie einen uses-Abschnitt vorfinden, suchen sie den Bezeichner im Abschnitt 'interface' der Units. Wird der Bezeichner gefunden, halten sie an. Das Ergebnis und einige Zwischenschritte werden gecached. Weil oftmals nur einige interface-Abschnitte durchsucht werden müssen, wird ein einzelner Bezeichner rasch gefunden.

Die CodeTools durchsuchen einen Quelltext nicht in einem Durchgang wie ein Kompiler, sondern in mehreren Durchgängen, abhängig von den Erfordernissen der aktuellen Funktion:

Jede Ebene hat ihre eigenen Caches, die vor dem Aufruf einer Funktion geprüft und aktualisiert werden müssen. Viele High-level-Funktionen, auf die mittels 'CodeToolBoss' zugegriffen werden kann, machen das automatisch. Für andere liegt die Verantwortung beim aufrufenden Prozess.

Ein Beispiel dafür:

unti1.pas:

pascal
unit Unit1;
{$I settings.inc}
interface
uses
  {$IFDEF Flag}
  unix,
  {$ELSE}
  windows,
  {$ENDIF}
  Classes;

settings.inc:

pascal
{%MainUnit unit1.pas}
{$DEFINE Flag}

clean source:

pascal
unit Unit1;
{$I settings.inc}{%MainUnit unit1.pas}
{$DEFINE Flag}
interface
uses
  {$IFDEF Flag}
  unix,
  {$ELSE}{$ENDIF}
  Classes;

Tipp: Um eine Unit einfach zu durchlaufen und die Knoten zu erstellen, verwenden Sie CodeToolBoss.Explore.

Clean Position und Kursorposition

Es gibt verschiedene Methoden, um in den CodeTools eine Position zu definieren.

Die absolute Position bezieht sich auf den Quelltext als Zeichenkette und beginnt bei 1. Beispielsweise hält ein TCodeBuffer den Dateiinhalt als Zeichenkette in der Eigenschaft 'Source'. Die Positionen der Einfügemarke oder des Kursors sind als X,Y gegeben, wobei Y die Zeilennummer ist (bei 1 beginnend) und X die Spaltennummer (bei 1 beginnend). Ein TCodeBuffer stellt zum Umwandeln die Funktionen LineColToPosition und AbsoluteToLineCol'' zur Verfügung. Wenn Sie mit mehreren Quelltextdateinen arbeiten, wie einer Unit, die aus verschiedenen Includedateien bestehen kann, dann bezieht sich 'Clean Position' auf die absolute Position im bereinigten CodeSrc**. Src ist eine Zeichenkette und Clean Positions beginnt bei 1. Die Kursorpositionen werden angegeben als TCodeXYPosition (Code,X,Y). Ein TCodeTool stellt zum Umwandeln die FunktionenCaretToCleanPos,**CleanPosToCaret''' zur Verfügung.

Einfügen, Löschen und Ersetzen - der TSourceChangeCache

Wenn Sie Änderungen am Quelltext einer Unit (oder ihrer Includedateien) vornehmen, sollten Sie dazu 'CodetoolBoss.SourceChangeCache' benutzen, weil:

Verwendung

Der SourceChangeCache arbeitet mit einer Unit, deshalb müssen Sie ein TCodeTool nehmen und eine Unit/Includedatei damit scannen. Zum Beispiel:

pascal
  // Schritt 1: lade die Datei und untersuche sie
  Code:=CodeToolBoss.LoadFile(Filename,false,false);
  if Code=nil then
    raise Exception.Create('loading failed '+Filename);
  if not CodeToolBoss.Explore(Code,Tool,false) then
    ...;// Fehler beim Untersuchen ...

  // Schritt 2: verbinde mit dem SourceChangeCache
  CodeToolBoss.SourceChangeCache.MainScanner:=Tool.Scanner;

  // Schritt 3: nimm Replace zum Einfügen und/oder Löschen von Code.
  // Die beiden ersten Parameter sind die benötigten Leerzeichen vor und hinter der Einfügestelle.
  // FromPos, ToPos legen den gelöschten/ersetzten Bereich in CleanPos-Positionen fest.
  // NewCode ist die Zeichenkette des neuen Codes. Verwenden Sie '' zum Löschen.
  if not CodeToolBoss.SourceChangeCache.Replace(gtNone,gtNone,FromPos,ToPos,NewCode) then
    exit; // z.B. Quelltext ist nicht beschreibbar oder ein vorangegangenes Ersetzen hat diese Stelle gelöscht
  ...einige weitere Ersetzungen...

  // Schritt 4: wende die Änderungen an
  if not CodeToolBoss.SourceChangeCache.Apply then
    exit; // Anwendung wurde abgebrochen

BeginUpdate/EndUpdate

BeginUpdate/EndUpdate verzögert die Anwendung. Dies ist nützlich, wenn Sie verschiedene Code ändernde Funktionen kombinieren. Zum Beispiel:

Sie wollen die Unit scannen, fügen eine Unit in der uses-Klausel des Interface-Bereichs hinzu und entfernen die Unit aus der uses-Klausel des Implementation-Bereichs. Die zwei Funktionen 'AddUnitToMainUsesSection' und 'RemoveUnitFromUsesSection' benutzen 'Apply', ändern den Quelltext, sodass die zweite Funktion die Unit ein zweites Mal scannen würde. Weil aber beide Funktionen voneinander unabhängig sind (Sie verändern verschiedene Teile des Quelltextes) können Sie beide miteinander kombinieren und nur einen Scan machen:

pascal
  // Schritt 1: durchsuche die Unit und verbinde mit SourceChangeCache
  if not CodeToolBoss.Explore(Code,Tool,false) then
    ...;// Fehler beim Untersuchen ...
  CodeToolBoss.SourceChangeCache.MainScanner:=Tool.Scanner;

  // Schritt 2: verzögere die Anwendung
  CodeToolBoss.SourceChangeCache.BeginUpdate;

  // Schritt 3: füge die Unit zum Interface-Bereich hinzu
  // AddUnitToMainUsesSection würde angewendet und den Code ändern
  // Wegen BeginUpdate finden die Änderungen noch nicht statt, werden aber in SourceChangeCache gespeichert
  if not Tool.AddUnitToMainUsesSection('Classes','',CodeToolBoss.SourceChangeCache) then exit;

  // Schritt 4: entferne die Unit aus dem Implementation-Bereich
  // Ohne BeginUpdate würde RemoveUnitFromUsesSection die Unit erneut scannen
  if Tool.FindImplementationUsesSection<>nil then
    if not Tool.RemoveUnitFromUsesSection(Tool.FindImplementationUsesSection,'Classes',CodeToolBoss.SourceChangeCache) then exit;

  // Schritt 5: wende alle Änderungen an
  if not CodeToolBoss.SourceChangeCache.EndUpdate then
    exit; // Anwendung wurde abgebrochen

BeginUpdate/EndUpdate arbeiten mit einem Zähler, wenn Sie also BeginUpdate zwei Mal aufrufen, müssen Sie auch EndUpdate zwei Mal aufrufen. Dies bedeutet, dass Sie obiges Beispiel in eine Funktion stellen und mit einer weiteren Funktion kombinieren können.

Speichern Sie die Änderungen auf Disk

Die obigen Änderungen werden nur in den Codepuffern gemacht und diese Puffer als 'verändert' markiert. Um die Änderungen auf Disk zu speichern, müssen Sie für jeden veränderten Puffer 'Save' aufrufen.

Links


From the Free Pascal wiki, page "Codetools/de", as it stood on 2020-02-11 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 5, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.