Sign in Join
Wiki copytemporary

Codetools/ru: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11# Что такое codetools?
22
33Codetools - это пакет Lazarus, предоставляющий инструменты для анализа, изучения, редактирования и рефакторинга исходных кодов Pascal. Codetools был упакован в своем собственном модуле и лицензирован под лицензией GPL. Многие примеры, показывающие, как использовать codetools в ваших собственных программах, можно найти в components/codetools/examples.
44
55svn:
66
77- Lazarus: <http://svn.freepascal.org/svn/lazarus/trunk>
88- Только CodeTools: <http://svn.freepascal.org/svn/lazarus/trunk/components/codetools>
99
1010# Использование codetools без IDE
1111
1212Вы можете использовать codetools без IDE. Это может быть использовано для тестирования нового инструмента. Простой пример
1313
14-```
14+```text
1515 <lazarusdir>/components/codetools/examples/methodjumping.lpi
1616```
1717
1818Чтобы проверить декларацию find, codetools необходимо проанализировать исходники. Особенно исходники RTL и FCL. В примерах используются следующие переменные среды:
1919
2020- FPCDIR: путь к исходникам FPC, по умолчанию это *~/freepascal/fpc*.
2121- PP: pпуть к исполняемому файлу компилятора (/usr/bin/fpc or /usr/bin/ppc386 or C:\lazarus\ppc386.exe). Codetools нужно спросить компилятор о настройках. По умолчанию поиск 'fpc' осуществляется через переменную PATH.
2222- FPCTARGETOS: скажите codetools сканировать другую операционную систему (кросс-компиляция). Например: linux, freebsd, darwin, win32, win64, wince
2323- FPCTARGETCPU: при сканировании для другого процессора. Например: i386, powerpc, x86_64, arm, sparc
2424- LAZARUSDIR: путь к исходникам Lazarus. Требуется только если вы хотите их сканировать.
2525
2626FPC - очень сложный проект с множеством путей поиска, включающих файлы и макросы. Codetools должен знать все эти пути и макросы для анализа этих джунглей. Чтобы легко все это настроить, codetools содержит предопределенные шаблоны для исходных каталогов FPC, Lazarus, Delphi и Kylix.
2727
2828Смотрите пример объявления поиска
2929
30-```
30+```text
3131 <lazarusdir>/components/codetools/examples/finddeclaration.lpi
3232```
3333
3434Поскольку исходники FPC содержат несколько версий некоторых модулей, и исходники FPC часто меняются, codetools не используют фиксированную таблицу путей, а скорее сканируют всю структуру каталогов FPC при первом использовании, применяя набор правил, определяющих, что это - правильный исходник для текущих TargetOS и TargetCPU. Это сканирование может занять некоторое время в зависимости от скорости вашего диска. Все примеры сохраняют результат в **codetools.config**, так что при следующем запуске Lazarus это возможно длительное сканирование будет пропущено.
3535
3636Когда бы ни изменялись исходники FPC или переименовывалось устройство, просто удалите файл **codetools.config**. IDE Lazarus имеет свой собственный файл конфигурации и выполняет повторное сканирование всякий раз, когда изменяется исполняемый файл компилятора (или когда пользователь вызывает 'Tools \> Rescan FPC source directory').
3737
3838## Задание путей поиска и макросов
3939
4040Codetools использует \[конструкцию\] "define templates" (шаблоны определений) для генерации путей поиска и макросов. Шаблон определений является деревом правил.
4141
4242Вот пример того, как расширить глобальный путь включения и запросить путь включения каталога:
4343
4444``` pascal
4545uses
4646 Classes, SysUtils, CodeToolManager, DefineTemplates, FileProcs;
4747
4848var
4949 Directory: String;
5050 IncPathTemplate: TDefineTemplate;
5151begin
5252 Directory:=ExpandFileNameUTF8(GetCurrentDirUTF8);
5353
5454 // добавление подшаблона для расширения включающего пути поиска #IncPath.
5555 IncPathTemplate:=TDefineTemplate.Create(
5656 'Add myincludes to the IncPath', // имя шаблона, полезно для его поиска в дальнейшем (необязательно)
5757 'Add /tmp/myincludes to the include search path', // описание (необязательно)
5858 IncludePathMacroName, // имя переменной: #IncPath
5959 '$('+IncludePathMacroName+');/tmp/myincludes' // новое значение: $(#IncPath);/tmp/myincludes
6060 ,da_DefineRecurse
6161 );
6262 // добавляем шаблон включающего пути в дерево
6363 CodeToolBoss.DefineTree.Add(IncPathTemplate);
6464
6565 writeln('Directory="',Directory,'"',
6666 ' IncPath="',CodeToolBoss.GetIncludePathForDirectory(Directory),'"');
6767end.
6868```
6969
7070## Шаблон определений макроса
7171
7272Макросы, заданные \[при помощи\] шаблона определений, используются синтаксическим анализатором Pascal. В Codetools есть функции, позволяющие запрашивать у Free Pascal Compiler свои макросы и преобразовывать их для шаблонов определений. Это делается \[с помощью\] `CodeToolBoss.Init(Options);`, который вы можете найти во многих примерах.
7373
7474Кроме того, есть несколько предопределенных макросов, которые начинаются с хеша `(#)`. См. модуль `definetemplates` для \[получения\] полного списка. Вот несколько важных \[из них\]:
7575
7676``` pascal
7777 ExternalMacroStart = '#';
7878 // Стандартные макросы
7979 DefinePathMacroName = ExternalMacroStart+'DefinePath'; // текущий каталог
8080 UnitPathMacroName = ExternalMacroStart+'UnitPath'; // путь поиска объекта, разделенный точкой с запятой (такой же, как для FPC)
8181 IncludePathMacroName = ExternalMacroStart+'IncPath'; // путь поиска включаемого файла, разделенный точкой с запятой (такой же, как для FPC)
8282 SrcPathMacroName = ExternalMacroStart+'SrcPath'; // путь поиска исходника модуля, разделенный точкой с запятой (не указывается для FPC)
8383```
8484
8585Например, **IncludePathMacroName** - это **\#IncPath** и используется для определения пути поиска включаемого файла. Имейте в виду, что значения макросов зависят от каталога.
8686
8787Значения шаблонов определений могут содержать макросы. Макрос должен быть заключен в \[символ\] доллара и скобки: **\$(macro)**.
8888
8989В приведенном выше примере значение было *'\$('+*IncludePathMacroName*+');/tmp/myinclude'*, которое эквивалентно *'\$(#IncPath);/tmp/myinclude'*, и которое выполняется для старого включаемого пути поиска + *;/tmp/myinclude*, что означает добавление пути. Для удобства чтения вы можете использовать константу **IncludePathMacro** вместо *'\$('+IncludePathMacroName+')'*:
9090
9191``` pascal
9292 DefinePathMacro = '$('+DefinePathMacroName+')'; // путь к определенному шаблону
9393 UnitPathMacro = '$('+UnitPathMacroName+')';
9494 IncludePathMacro = '$('+IncludePathMacroName+')';
9595 SrcPathMacro = '$('+SrcPathMacroName+')';
9696```
9797
9898## Шаблон определений действий
9999
100100Шаблон определений имеет имя, необязательное описание, переменную, значение и действие. Имя и описание не являются обязательными. Значение переменной и значение \[шаблона определений\] зависит от действия. Вы можете добавить шаблоны определения как дочерние элементы шаблонов определения - создавая дерево шаблонов определения. Вы можете увидеть много примеров для определения шаблонов в диалоговом окне Lazarus'а *Tools / CodeTools Defines Editor*.
101101
102102- da_Block - используется для группировки шаблонов. Когда блок выполняется, выполняются и все дочерние элементы.
103103- da_Directory - используйте это, чтобы определить все правила каталога. Если это корневой каталог, задайте для параметра Value полный развернутый путь к каталогу (используйте функцию `CleanAndExpandDirectory`). Если это подкаталог (родительский шаблон - это каталог), то значение - это подкаталог. Может содержать макросы. Дочерние объекты выполняются только в том случае, если каталог соответствует.
104104- da_Define - устанавливает значение (Value) макроса (Variable) текущего каталога. Значение может содержать макросы. Обратите внимание, что когда значение макроса установлено в пустую строку *, оно все еще определено, это означает, что*{\$IFDEF variable}*все равно будет*true''. Дочерние элементы не выполняются.
105105- da_Undefine - очищает макрос (Variable) текущего каталога. *{\$IFDEF macro}* является равным *false*. Дочерние элементы не выполняются.
106106- da_DefineRecurse - как и da_Define, но для текущего каталога и подкаталогов.
107107- da_UndefineRecurse - как и da_Undefine, но для текущего каталога и подкаталогов.
108108- da_UndefineAll - очищает все значения макросов.
109109- da_IfDef - если макрос *Variable* определен, тогда выполняются дочерние элементы и пропускаются следующие da_Else и da_ElseIf.
110110- da_IfNDef - если макрос *Variable* не определен, тогда выполняются дочерние элементы и пропускаются следующие da_Else и da_ElseIf.
111111- da_If,daElseIf - если выполнение логического выражения *Value* приводит к true, тогда выполняются дочерние элементы и пропускаются следующие da_Else и da_ElseIf. Значение может содержать макросы.
112112- da_Else - когда этот шаблон будет выполнен, выполняются все дочерние элементы.
113113
114114## Как расширить включаемый путь каталога
115115
116116См. пример lazarus/components/codetools/examples/setincludepath.lpr. Он демонстрирует использование относительных путей, абсолютных путей, как использовать DefinePathMacro и разницу между da_Define и da_DefineRecurse.
117117
118118# Использование codetools в IDE с IDEIntf
119119
120120См. пакет \<lazarusdir\>/examples/idequickfix/quickfixexample.lpk. Он демонстрирует:
121121
122122- Как написать пакет IDE. Когда вы устанавливаете этот пакет, он регистрирует элемент Quick Fix в IDE.
123123- Как написать элемент Quick Fix для сообщения компилятора: 'Parameter "Sender" not used' (Параметр "Sender" не используется)
124124- Как использовать codetools для:
125125 - \[синтаксического\] разбора модуля
126126 - преобразования данных Filename, Line и Column в исходную позицию codetools
127127 - поиска узла codetools в позиции курсора
128128 - поиска узла процедуры и узла `begin..end`
129129 - создания прекрасной позиции вставки для оператора в начале блока `begin..end`
130130 - получения информации об отступах строки, чтобы новая строка работала также в подпроцедуре
131131 - вставки кода, используя codetools
132132
133133# Правила Codetools для исходников FPC
134134
135135Когда codetools ищет исходник FPC-процессора, он использует набор правил. Вы можете написать свои собственные правила, но обычно вы будете использовать стандартные правила, которые определены в include-файле components/codetools/fpcsrcrules.inc. Вы можете проверить правила с помощью утилиты командной строки: components/codetools/examples/testfpcsrcunitrules.lpi.
136136
137137## Использование testfpcsrcunitrules
138138
139139 Usage: lazarus/components/codetools/examples/testfpcsrcunitrules -h
140140
141141 -c <compiler file name>, --compiler=<compiler file name>
142142 По умолчанию используется переменная окружения PP.
143143 Если это не установлено, ищите fpc
144144
145145 -T <target OS>, --targetos=<target OS>
146146 По умолчанию используется переменная окружения FPCTARGET.
147147 Если это не установлено, используйте компилятор по умолчанию.
148148
149149 -P <target CPU>, --targetcpu=<target CPU>
150150 По умолчанию используется переменная окружения FPCTARGETCPU.
151151          Если это не установлено, используйте компилятор по умолчанию.
152152
153153 -F <FPC source directory>, --fpcsrcdir=<FPC source directory>
154154 По умолчанию используется переменная окружения FPCDIR.
155155          Значения по умолчанию нет.
156156
157157 -u <unit name>, --checkunit=<unit name>
158158 Напишите подробный отчет об этом модуле.
159159
160160## Пример для testfpcsrcunitrules
161161
162162Откройте testfpcsrcunitrules.lpi в IDE и скомпилируйте его. Затем запустите утилиту в терминале/консоли:
163163
164-```
164+```text
165165./testfpcsrcunitrules -F ~/fpc/sources/2.5.1/fpc/
166166```
167167
168168Это скажет вам, какой компилятор используется, какой компилятор выполняется, какие файлы конфигурации были протестированы и проанализированы, и предупредит вас о дублирующих модулях в пути поиска FPC и о дублировании исходных файлов модулей.
169169
170170> **Note:** В этом примере результаты кэшируются в файле *codetools.config*. Вы должны удалить *codetools.config* при обновлении компилятора или файла fpc.cfg.
171171
172172## Дубликаты исходных файлов
173173
174174\[Допустим,\] вы обнаруживаете, что codetools открывает для целевого wince/arm неправильный исходник модуля *mmsystem*. Запустите инструмент с параметром -u:
175175
176176``` pascal
177177./testfpcsrcunitrules -F ~/fpc/2.5.1/fpc/ -T wince -P arm -u mmsystem
178178```
179179
180180Это даст вам подробный отчет о том, где был найден этот модуль и какую оценку получил каждый исходный файл. Например:
181181
182182Unit report for mmsystem
183183
184-```
184+```text
185185WARNING: mmsystem is not in PPU search path
186186GatherUnitsInFPCSources UnitName=mmsystem File=packages/winunits-base/src/mmsystem.pp Score=11
187187GatherUnitsInFPCSources UnitName=mmsystem File=packages/winceunits/src/mmsystem.pp Score=11 => duplicate
188188```
189189
190190Это означает, что есть два исходных файла с одинаковым счетом, поэтому инструменты кодинга взяли первый. Последний в модулях wince предназначен для целевой \[платформы\] wince, а первый - для win32 и win64.
191191
192192Теперь откройте файл правил fpcsrcrules.inc.
193193
194194Правила работают так:
195195
196196``` pascal
197197Score:=10;
198198Targets:='wince';
199199Add('packages/winceunits');
200200```
201201
202202**Add** добавляет правило для всех файлов, начинающихся с 'packages/winceunits', которое добавляет 10 баллов ко всем этим файлам. **Targets** - это список целевых операционных систем и/или целевых процессоров через запятую. Например, Targets='wince,linux,i386' означает: применить эти правила к TargetOS wince или linux и ко всем TargetCPU i386.
203203
204204# Как codetools анализирует источники по-другому, нежели компилятор
205205
206206Компилятор оптимизирован для линейного анализа кода и загрузки необходимых модулей и включаемых файлов, как только он анализирует секцию uses или директиву. Codetools оптимизирован для анализа только определенных разделов кода. Например, для перехода от объявления метода к телу метода нужен только модуль и его включаемые файлы. Когда codetool ищет объявление, он ищет в обратном направлении. Это означает, что он начинает поиск в локальных переменных, а затем вверх от \[секции\] implementation. Когда он находит секцию uses, он ищет идентификаторы в секции interface модулей. Когда идентификатор найден, он останавливается. Результат и некоторые промежуточные шаги кэшируются. Поскольку часто требуется проанализировать только несколько разделов интерфейса, он очень быстро находит индивидуальный идентификатор.
207207
208208Codetools анализируют источник не за один шаг (как это делает компилятор), а за несколько шагов, которые зависят от того, что нужно текущему codetool:
209209
210210- Сначала исходный файл загружается в TCodeBuffer. В среде IDE этот шаг используется для изменения кодировки на UTF8. Файлы хранятся в памяти и перезагружаются только в случае изменения даты изменения или возврата файла вручную. Есть несколько инструментов и функций, которые работают непосредственно с буфером.
211211- Следующим шагом является анализ модуля (или include-файла). Модуль должен анализироваться с самого начала, поэтому codetools пытается найти основной файл, первый файл модуля. Это достигается путем поиска директивы в первой строке, например {% MainUnit ../lclintf.pp}. Если этого не существует, он выполняет поиск в кэше includelink. Среда IDE сохраняет этот кэш на диск, поэтому среда IDE обучается с течением времени.
212212- После нахождения основного файла TLinkScanner анализирует источник. Он обрабатывает директивы компилятора, такие как директивы include и директивы условной компиляции. Сканеру может быть задан диапазон, например, он может анализировать только интерфейс модулей. Сканер создает *чистый исходник*. Чистый исходный код составляется из всех включаемых файлов, очищенных от директив условной компиляции *else*, которые пропускаются. Он также создает список **ссылок**, которые отображают чистый исходный код в реальные исходные файлы. Чистым исходным кодом теперь является Pascal, не содержащий кода *else*. Примечание: есть также инструменты, предназначенные для сканирования единого исходного кода для всех директив. Эти инструменты создают дерево директив.
213213- После создания очищенного исходника TCodeTool анализирует его и создает дерево TCodeTreeNode. Он также может указать диапазон. Этот анализатор пропускает несколько частей, например члены класса, блоки `begin..end` и списки параметров. Многим инструментам они не нужны. Эти подузлы создаются по запросу. У TCodeTreeNode есть диапазон `StartPos..EndPos`, который является чистой позицией, то есть позицией в очищенном исходнике. Есть только узлы для важных частей. Создание узлов для каждой детали требует больше памяти, чем сам исходник, и \[на практике\] редко востребовано. Существует множество функций, чтобы узнать детали. Например, если функция имеет соглашение о вызовах 'cdecl'.
214214- При поиске идентификатора поиск сохраняет базовые типы, которые он находит, и создает кэши для всех идентификаторов в разделе interface.
215215
216216Каждый уровень имеет свои собственные кэши, которые необходимо проверять и обновлять перед вызовом функции. Многие функции высокого уровня, доступные через CodeToolBoss, делают это автоматически. Для других ответственность за это лежит на \[том, кто их\] вызывает.
217217
218218Пример для:
219219
220220unit1.pas:
221221
222222``` pascal
223223unit Unit1;
224224{$I settings.inc}
225225interface
226226uses
227227 {$IFDEF Flag}
228228 unix,
229229 {$ELSE}
230230 windows,
231231 {$ENDIF}
232232 Classes;
233233```
234234
235235settings.inc:
236236
237237``` pascal
238238{%MainUnit unit1.pas}
239239{$DEFINE Flag}
240240```
241241
242242очищенный исходник:
243243
244244``` pascal
245245unit Unit1;
246246{$I settings.inc}{%MainUnit unit1.pas}
247247{$DEFINE Flag}
248248interface
249249uses
250250 {$IFDEF Flag}
251251 unix,
252252 {$ELSE}{$ENDIF}
253253 Classes;
254254```
255255
256256Подсказка: чтобы было легко разобрать модуль и построить узлы, используйте **CodeToolBoss.Explore**.
257257
258258# CleanPos и CursorPos
259259
260260Есть несколько методов для определения позиции в codetools.
261261
262262Абсолютная позиция codetools связана с исходником как непрерывная строка, начинающаяся с символа 1. Например, TCodeBuffer хранит содержимое файла как одну строку в своем свойстве Source. Позиции каретки или курсора задаются как X,Y, где X - номер столбца, а Y - номер строки. Каждое значение (X и Y) начинается с 1. TCodeBuffer предоставляет функции-члены **LineColToPosition** и **AbsoluteToLineCol** для преобразования между значениями (X, Y) и абсолютной позицией codetools. При работе с несколькими исходными файлами (например, модулем, который может содержать несколько включаемых файлов), чистая позиция относится к абсолютной позиции в разобранном коде **Src**. Здесь Src - строка, чья чистая позиция начинаются с 1. Позиция курсора указывается как TCodeXYPosition (Code,X,Y). TCodeTool предоставляет функции **CaretToCleanPos** и **CleanPosToCaret** для преобразования между ними.
263263
264264# Вставка, удаление, замена - TSourceChangeCache
265265
266266При внесении изменений в исходный код модуля (или его включаемых файлов) вы должны использовать \[функцию\] `CodetoolBoss.SourceChangeCache` вместо непосредственного изменения исходника.
267267
268268- Простое использование: Connect, Replace, Replace, ... Apply. См. ниже.
269269- Вы можете использовать cleanpos, как указано в дереве узлов, ИЛИ вы можете использовать точное положение в файле.
270270- Вы можете использовать Replace для вставки и удаления, что автоматически вызывает события, поэтому подключенные редакторы уведомляются об изменениях.
271271- Он может автоматически вставлять необходимые пробелы, разрывы строк или пустые строки перед или после каждой замены. Например, вы определяете, что впереди должна быть пустая строка. SourceChangeCache проверяет, что вставлено и сколько места уже есть, и вставит необходимое пространство.
272272- Он проверяет, доступен ли для записи замененный/удаленный диапазон.
273273- Вы можете делать множественные замены и контролировать \[процесс\], когда они применяются. Имейте в виду, что вставка кода означает, что проанализированное дерево становится недействительным и нуждается в перестройке.
274274- Множественные замены проверяются на пересечение. Например, вставка в середине удаленного кода выдает ошибку.
275275- Несколько вставок в одном месте добавляются \[по принципу\] FIFO - сначала сверху.
276276- Вы можете объединить несколько функций, изменяя код в одну большую функцию. См. ниже.
277277
278278## Использование
279279
280280SourceChangeCache работает с модулем, поэтому вам нужно получить TCodeTool и отсканировать модуль/include-файл. Например:
281281
282282``` pascal
283283 // Шаг 1: загружаем файл и парсим его
284284 Code:=CodeToolBoss.LoadFile(Filename,false,false);
285285 if Code=nil then
286286 raise Exception.Create('loading failed '+Filename);
287287 if not CodeToolBoss.Explore(Code,Tool,false) then
288288 ...;// parse error ...
289289
290290 // Шаг 2: подключаем SourceChangeCache
291291 CodeToolBoss.SourceChangeCache.MainScanner:=Tool.Scanner;
292292
293293 // Шаг 3: используем Replace для вставки и/или удаления кода
294294 // Первые два параметра - это необходимые пробелы спереди и позади вставки
295295 // FromPos, ToPos определяют удаляемый/заменяемый диапазон в позиции CleanPos.
296296 // NewCode - это строка нового кода. Используем '' для удаления.
297297 if not CodeToolBoss.SourceChangeCache.Replace(gtNone,gtNone,FromPos,ToPos,NewCode) then
298298 exit; // например, исходник [оказался] только для чтения или шаблон Replace удалил место
299299 ...еще немного применяем Replace...
300300
301301 // Шаг 4: Применяем изменения
302302 if not CodeToolBoss.SourceChangeCache.Apply then
303303 exit; // применение было прервано
304304```
305305
306306## BeginUpdate/EndUpdate
307307
308308BeginUpdate/EndUpdate задерживают \[немедленное\] применение \[изменений\]. Это полезно при объединении нескольких функций изменения кода. Например:
309309
310310Вы хотите отсканировать модуль, добавить модуль в секцию uses раздела interface, удалив \[его\] из секции uses раздела implementation. Две функции AddUnitToMainUsesSection и RemoveUnitFromUsesSection используют \[метод\] Apply, изменяя исходник, поэтому вторая функция будет повторно сканировать модуль во второй раз. Но так как эти две функции не зависят друг от друга (они изменяют разные части источника), вы можете объединить их и сделать это за одно сканирование:
311311
312312``` pascal
313313 // Шаг 1: парсим модуль и подключаем SourceChangeCache
314314 if not CodeToolBoss.Explore(Code,Tool,false) then
315315 ...;// ошибка парсинга ...
316316 CodeToolBoss.SourceChangeCache.MainScanner:=Tool.Scanner;
317317
318318 // Шаг 2: задерживаем [применение метода] Apply
319319 CodeToolBoss.SourceChangeCache.BeginUpdate;
320320
321321 // Шаг 3: добавляем модуль в секцию uses раздела interface
322322 // AddUnitToMainUsesSection будет применяться и изменять код
323323 // Из-за BeginUpdate изменение еще не сделано, но сохранено в SourceChangeCache
324324 if not Tool.AddUnitToMainUsesSection('Classes','',CodeToolBoss.SourceChangeCache) then exit;
325325
326326 // Шаг 4: удаляем модуль из секции uses раздела implementation
327327 // Без BeginUpdate RemoveUnitFromUsesSection будет повторно сканировать модуль
328328 if Tool.FindImplementationUsesSection<>nil then
329329 if not Tool.RemoveUnitFromUsesSection(Tool.FindImplementationUsesSection,'Classes',CodeToolBoss.SourceChangeCache) then exit;
330330
331331 // Шаг 5: применяем все изменения
332332 if not CodeToolBoss.SourceChangeCache.EndUpdate then
333333 exit; // применение было прервано
334334```
335335
336336BeginUpdate/EndUpdate работают со счетчиком, поэтому, если вы вызываете BeginUpdate дважды, вам нужно дважды вызывать EndUpdate. Это означает, что вы можете поместить приведенный выше пример в функцию и объединить ее с другой функцией.
337337
338338## Сохранение изменений на диск
339339
340340Вышеуказанные изменения вносятся в буферы кода, и буферы помечаются как измененные. Чтобы сохранить изменения на диске, вы должны вызвать Save для каждого измененного буфера.
341341
342342- Буферы, которые будут изменены в следующем Apply/EndUpdate, находятся в `SourceChangeCache.BuffersToModify` и `BuffersToModifyCount`.
343343- События `SourceChangeCache.OnBeforeApplyChanges/OnAfterApplyChanges` используются CodeToolBoss, который подключает их к собственным `OnBeforeApplyChanges/OnAfterApplyChanges`. Среда Lazarus IDE устанавливает эти события и автоматически открывает измененные файлы в редакторе исходного кода, поэтому все изменения попадают в список отмены synedit.
344344
345345# Подсказки/Советы/Руководства
346346
347347- BuildTree проверяет текущее состояние и будет анализировать \[код\] только при необходимости. Если предыдущий вызов проанализировал интерфейс, и вам снова нужен интерфейс, BuildTree ничего не сделает. Если вам нужен весь модуль, будет проанализирован только раздел implementation. Узлы освобождаются только в том случае, если некоторые файлы изменились на диске или изменились некоторые настройки (исходные макросы). BuildTree не проверяет все файлы при каждом вызове. Вместо этого он использует каталог кеша codetools. Так что, если ничего не изменилось, он вернется очень быстро. Вы должны вызвать его перед любой операцией поиска.
348348- **Не** вызывайте BuildTree **после** операции \[проверки\]. Это пустая трата \[ресурсов\] процессора.
349349- BuildTree вызывает исключение, когда отсутствуют include-файлы или \[имеются\] синтаксические ошибки. Вы должны приложить к своему коду \[следующую конструкцию\]
350350
351351``` pascal
352352try
353353 Tool.BuildTree(lsrEnd);
354354 ... поиск ... замена
355355except
356356 on E: Exception do
357357 CodeToolBoss.HandleException(E);
358358end;
359359```
360360
361361- After calling SourceChangeCache.Replace (multiple times) the sources (TCodeBuffers) have not changed immediately. You must call SourceChangeCache.Apply to change the sources. This will not save the changes to file.
362362- После вызова `SourceChangeCache.Replace` (несколько раз) исходники (TCodeBuffers) не изменяются сразу. Вы должны вызвать `SourceChangeCache.Apply`, чтобы изменить исходники. \[Но\] это не сохраняет изменения в файл.
363363
364364# Ссылки
365365
366366- [[Lazarus IDE Tools/ru|Lazarus IDE Tools]] - Учебник по встроенным инструментам стандартной IDE
367367- [[Cody]] - Пакет IDE, добавляющий продвинутые инструменты кода в IDE
368368- [[Extending the IDE/ru|Extending the IDE]] - Как написать свои собственные плагины codetools для IDE.
369369
370370---
371371*From the Free Pascal wiki, page "Codetools/ru", 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](/wiki-contact).*

Back to history