Sign in Join
Wiki copytemporary

Codetools/ru: what changed

Revision 1 to 2. 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-` <lazarusdir>/components/codetools/examples/methodjumping.lpi`
14+```
15+ <lazarusdir>/components/codetools/examples/methodjumping.lpi
16+```
1517
1618Чтобы проверить декларацию find, codetools необходимо проанализировать исходники. Особенно исходники RTL и FCL. В примерах используются следующие переменные среды:
1719
1820- FPCDIR: путь к исходникам FPC, по умолчанию это *~/freepascal/fpc*.
1921- PP: pпуть к исполняемому файлу компилятора (/usr/bin/fpc or /usr/bin/ppc386 or C:\lazarus\ppc386.exe). Codetools нужно спросить компилятор о настройках. По умолчанию поиск 'fpc' осуществляется через переменную PATH.
2022- FPCTARGETOS: скажите codetools сканировать другую операционную систему (кросс-компиляция). Например: linux, freebsd, darwin, win32, win64, wince
2123- FPCTARGETCPU: при сканировании для другого процессора. Например: i386, powerpc, x86_64, arm, sparc
2224- LAZARUSDIR: путь к исходникам Lazarus. Требуется только если вы хотите их сканировать.
2325
2426FPC - очень сложный проект с множеством путей поиска, включающих файлы и макросы. Codetools должен знать все эти пути и макросы для анализа этих джунглей. Чтобы легко все это настроить, codetools содержит предопределенные шаблоны для исходных каталогов FPC, Lazarus, Delphi и Kylix.
2527
2628Смотрите пример объявления поиска
2729
28-` <lazarusdir>/components/codetools/examples/finddeclaration.lpi`
30+```
31+ <lazarusdir>/components/codetools/examples/finddeclaration.lpi
32+```
2933
3034Поскольку исходники FPC содержат несколько версий некоторых модулей, и исходники FPC часто меняются, codetools не используют фиксированную таблицу путей, а скорее сканируют всю структуру каталогов FPC при первом использовании, применяя набор правил, определяющих, что это - правильный исходник для текущих TargetOS и TargetCPU. Это сканирование может занять некоторое время в зависимости от скорости вашего диска. Все примеры сохраняют результат в **codetools.config**, так что при следующем запуске Lazarus это возможно длительное сканирование будет пропущено.
3135
3236Когда бы ни изменялись исходники FPC или переименовывалось устройство, просто удалите файл **codetools.config**. IDE Lazarus имеет свой собственный файл конфигурации и выполняет повторное сканирование всякий раз, когда изменяется исполняемый файл компилятора (или когда пользователь вызывает 'Tools \> Rescan FPC source directory').
3337
3438## Задание путей поиска и макросов
3539
3640Codetools использует \[конструкцию\] "define templates" (шаблоны определений) для генерации путей поиска и макросов. Шаблон определений является деревом правил.
3741
3842Вот пример того, как расширить глобальный путь включения и запросить путь включения каталога:
3943
4044``` pascal
4145uses
4246 Classes, SysUtils, CodeToolManager, DefineTemplates, FileProcs;
4347
4448var
4549 Directory: String;
4650 IncPathTemplate: TDefineTemplate;
4751begin
4852 Directory:=ExpandFileNameUTF8(GetCurrentDirUTF8);
4953
5054 // добавление подшаблона для расширения включающего пути поиска #IncPath.
5155 IncPathTemplate:=TDefineTemplate.Create(
5256 'Add myincludes to the IncPath', // имя шаблона, полезно для его поиска в дальнейшем (необязательно)
5357 'Add /tmp/myincludes to the include search path', // описание (необязательно)
5458 IncludePathMacroName, // имя переменной: #IncPath
5559 '$('+IncludePathMacroName+');/tmp/myincludes' // новое значение: $(#IncPath);/tmp/myincludes
5660 ,da_DefineRecurse
5761 );
5862 // добавляем шаблон включающего пути в дерево
5963 CodeToolBoss.DefineTree.Add(IncPathTemplate);
6064
6165 writeln('Directory="',Directory,'"',
6266 ' IncPath="',CodeToolBoss.GetIncludePathForDirectory(Directory),'"');
6367end.
6468```
6569
6670## Шаблон определений макроса
6771
6872Макросы, заданные \[при помощи\] шаблона определений, используются синтаксическим анализатором Pascal. В Codetools есть функции, позволяющие запрашивать у Free Pascal Compiler свои макросы и преобразовывать их для шаблонов определений. Это делается \[с помощью\] `CodeToolBoss.Init(Options);`, который вы можете найти во многих примерах.
6973
7074Кроме того, есть несколько предопределенных макросов, которые начинаются с хеша `(#)`. См. модуль `definetemplates` для \[получения\] полного списка. Вот несколько важных \[из них\]:
7175
7276``` pascal
7377 ExternalMacroStart = '#';
7478 // Стандартные макросы
7579 DefinePathMacroName = ExternalMacroStart+'DefinePath'; // текущий каталог
7680 UnitPathMacroName = ExternalMacroStart+'UnitPath'; // путь поиска объекта, разделенный точкой с запятой (такой же, как для FPC)
7781 IncludePathMacroName = ExternalMacroStart+'IncPath'; // путь поиска включаемого файла, разделенный точкой с запятой (такой же, как для FPC)
7882 SrcPathMacroName = ExternalMacroStart+'SrcPath'; // путь поиска исходника модуля, разделенный точкой с запятой (не указывается для FPC)
7983```
8084
8185Например, **IncludePathMacroName** - это **\#IncPath** и используется для определения пути поиска включаемого файла. Имейте в виду, что значения макросов зависят от каталога.
8286
8387Значения шаблонов определений могут содержать макросы. Макрос должен быть заключен в \[символ\] доллара и скобки: **\$(macro)**.
8488
8589В приведенном выше примере значение было *'\$('+*IncludePathMacroName*+');/tmp/myinclude'*, которое эквивалентно *'\$(#IncPath);/tmp/myinclude'*, и которое выполняется для старого включаемого пути поиска + *;/tmp/myinclude*, что означает добавление пути. Для удобства чтения вы можете использовать константу **IncludePathMacro** вместо *'\$('+IncludePathMacroName+')'*:
8690
8791``` pascal
8892 DefinePathMacro = '$('+DefinePathMacroName+')'; // путь к определенному шаблону
8993 UnitPathMacro = '$('+UnitPathMacroName+')';
9094 IncludePathMacro = '$('+IncludePathMacroName+')';
9195 SrcPathMacro = '$('+SrcPathMacroName+')';
9296```
9397
9498## Шаблон определений действий
9599
96100Шаблон определений имеет имя, необязательное описание, переменную, значение и действие. Имя и описание не являются обязательными. Значение переменной и значение \[шаблона определений\] зависит от действия. Вы можете добавить шаблоны определения как дочерние элементы шаблонов определения - создавая дерево шаблонов определения. Вы можете увидеть много примеров для определения шаблонов в диалоговом окне Lazarus'а *Tools / CodeTools Defines Editor*.
97101
98102- da_Block - используется для группировки шаблонов. Когда блок выполняется, выполняются и все дочерние элементы.
99103- da_Directory - используйте это, чтобы определить все правила каталога. Если это корневой каталог, задайте для параметра Value полный развернутый путь к каталогу (используйте функцию `CleanAndExpandDirectory`). Если это подкаталог (родительский шаблон - это каталог), то значение - это подкаталог. Может содержать макросы. Дочерние объекты выполняются только в том случае, если каталог соответствует.
100104- da_Define - устанавливает значение (Value) макроса (Variable) текущего каталога. Значение может содержать макросы. Обратите внимание, что когда значение макроса установлено в пустую строку *, оно все еще определено, это означает, что*{\$IFDEF variable}*все равно будет*true''. Дочерние элементы не выполняются.
101105- da_Undefine - очищает макрос (Variable) текущего каталога. *{\$IFDEF macro}* является равным *false*. Дочерние элементы не выполняются.
102106- da_DefineRecurse - как и da_Define, но для текущего каталога и подкаталогов.
103107- da_UndefineRecurse - как и da_Undefine, но для текущего каталога и подкаталогов.
104108- da_UndefineAll - очищает все значения макросов.
105109- da_IfDef - если макрос *Variable* определен, тогда выполняются дочерние элементы и пропускаются следующие da_Else и da_ElseIf.
106110- da_IfNDef - если макрос *Variable* не определен, тогда выполняются дочерние элементы и пропускаются следующие da_Else и da_ElseIf.
107111- da_If,daElseIf - если выполнение логического выражения *Value* приводит к true, тогда выполняются дочерние элементы и пропускаются следующие da_Else и da_ElseIf. Значение может содержать макросы.
108112- da_Else - когда этот шаблон будет выполнен, выполняются все дочерние элементы.
109113
110114## Как расширить включаемый путь каталога
111115
112116См. пример lazarus/components/codetools/examples/setincludepath.lpr. Он демонстрирует использование относительных путей, абсолютных путей, как использовать DefinePathMacro и разницу между da_Define и da_DefineRecurse.
113117
114118# Использование codetools в IDE с IDEIntf
115119
116120См. пакет \<lazarusdir\>/examples/idequickfix/quickfixexample.lpk. Он демонстрирует:
117121
118122- Как написать пакет IDE. Когда вы устанавливаете этот пакет, он регистрирует элемент Quick Fix в IDE.
119123- Как написать элемент Quick Fix для сообщения компилятора: 'Parameter "Sender" not used' (Параметр "Sender" не используется)
120124- Как использовать codetools для:
121125 - \[синтаксического\] разбора модуля
122126 - преобразования данных Filename, Line и Column в исходную позицию codetools
123127 - поиска узла codetools в позиции курсора
124128 - поиска узла процедуры и узла `begin..end`
125129 - создания прекрасной позиции вставки для оператора в начале блока `begin..end`
126130 - получения информации об отступах строки, чтобы новая строка работала также в подпроцедуре
127131 - вставки кода, используя codetools
128132
129133# Правила Codetools для исходников FPC
130134
131135Когда codetools ищет исходник FPC-процессора, он использует набор правил. Вы можете написать свои собственные правила, но обычно вы будете использовать стандартные правила, которые определены в include-файле components/codetools/fpcsrcrules.inc. Вы можете проверить правила с помощью утилиты командной строки: components/codetools/examples/testfpcsrcunitrules.lpi.
132136
133137## Использование testfpcsrcunitrules
134138
135139 Usage: lazarus/components/codetools/examples/testfpcsrcunitrules -h
136140
137141 -c <compiler file name>, --compiler=<compiler file name>
138142 По умолчанию используется переменная окружения PP.
139143 Если это не установлено, ищите fpc
140144
141145 -T <target OS>, --targetos=<target OS>
142146 По умолчанию используется переменная окружения FPCTARGET.
143147 Если это не установлено, используйте компилятор по умолчанию.
144148
145149 -P <target CPU>, --targetcpu=<target CPU>
146150 По умолчанию используется переменная окружения FPCTARGETCPU.
147151          Если это не установлено, используйте компилятор по умолчанию.
148152
149153 -F <FPC source directory>, --fpcsrcdir=<FPC source directory>
150154 По умолчанию используется переменная окружения FPCDIR.
151155          Значения по умолчанию нет.
152156
153157 -u <unit name>, --checkunit=<unit name>
154158 Напишите подробный отчет об этом модуле.
155159
156160## Пример для testfpcsrcunitrules
157161
158162Откройте testfpcsrcunitrules.lpi в IDE и скомпилируйте его. Затем запустите утилиту в терминале/консоли:
159163
160-`./testfpcsrcunitrules -F ~/fpc/sources/2.5.1/fpc/`
164+```
165+./testfpcsrcunitrules -F ~/fpc/sources/2.5.1/fpc/
166+```
161167
162168Это скажет вам, какой компилятор используется, какой компилятор выполняется, какие файлы конфигурации были протестированы и проанализированы, и предупредит вас о дублирующих модулях в пути поиска FPC и о дублировании исходных файлов модулей.
163169
164170> **Note:** В этом примере результаты кэшируются в файле *codetools.config*. Вы должны удалить *codetools.config* при обновлении компилятора или файла fpc.cfg.
165171
166172## Дубликаты исходных файлов
167173
168174\[Допустим,\] вы обнаруживаете, что codetools открывает для целевого wince/arm неправильный исходник модуля *mmsystem*. Запустите инструмент с параметром -u:
169175
170176``` pascal
171177./testfpcsrcunitrules -F ~/fpc/2.5.1/fpc/ -T wince -P arm -u mmsystem
172178```
173179
174180Это даст вам подробный отчет о том, где был найден этот модуль и какую оценку получил каждый исходный файл. Например:
175181
176182Unit report for mmsystem
177183
178-`WARNING: mmsystem is not in PPU search path`\
179-`GatherUnitsInFPCSources UnitName=mmsystem File=packages/winunits-base/src/mmsystem.pp Score=11`\
180-`GatherUnitsInFPCSources UnitName=mmsystem File=packages/winceunits/src/mmsystem.pp Score=11 => duplicate`
184+```
185+WARNING: mmsystem is not in PPU search path
186+GatherUnitsInFPCSources UnitName=mmsystem File=packages/winunits-base/src/mmsystem.pp Score=11
187+GatherUnitsInFPCSources UnitName=mmsystem File=packages/winceunits/src/mmsystem.pp Score=11 => duplicate
188+```
181189
182190Это означает, что есть два исходных файла с одинаковым счетом, поэтому инструменты кодинга взяли первый. Последний в модулях wince предназначен для целевой \[платформы\] wince, а первый - для win32 и win64.
183191
184192Теперь откройте файл правил fpcsrcrules.inc.
185193
186194Правила работают так:
187195
188196``` pascal
189197Score:=10;
190198Targets:='wince';
191199Add('packages/winceunits');
192200```
193201
194202**Add** добавляет правило для всех файлов, начинающихся с 'packages/winceunits', которое добавляет 10 баллов ко всем этим файлам. **Targets** - это список целевых операционных систем и/или целевых процессоров через запятую. Например, Targets='wince,linux,i386' означает: применить эти правила к TargetOS wince или linux и ко всем TargetCPU i386.
195203
196204# Как codetools анализирует источники по-другому, нежели компилятор
197205
198206Компилятор оптимизирован для линейного анализа кода и загрузки необходимых модулей и включаемых файлов, как только он анализирует секцию uses или директиву. Codetools оптимизирован для анализа только определенных разделов кода. Например, для перехода от объявления метода к телу метода нужен только модуль и его включаемые файлы. Когда codetool ищет объявление, он ищет в обратном направлении. Это означает, что он начинает поиск в локальных переменных, а затем вверх от \[секции\] implementation. Когда он находит секцию uses, он ищет идентификаторы в секции interface модулей. Когда идентификатор найден, он останавливается. Результат и некоторые промежуточные шаги кэшируются. Поскольку часто требуется проанализировать только несколько разделов интерфейса, он очень быстро находит индивидуальный идентификатор.
199207
200208Codetools анализируют источник не за один шаг (как это делает компилятор), а за несколько шагов, которые зависят от того, что нужно текущему codetool:
201209
202210- Сначала исходный файл загружается в TCodeBuffer. В среде IDE этот шаг используется для изменения кодировки на UTF8. Файлы хранятся в памяти и перезагружаются только в случае изменения даты изменения или возврата файла вручную. Есть несколько инструментов и функций, которые работают непосредственно с буфером.
203211- Следующим шагом является анализ модуля (или include-файла). Модуль должен анализироваться с самого начала, поэтому codetools пытается найти основной файл, первый файл модуля. Это достигается путем поиска директивы в первой строке, например {% MainUnit ../lclintf.pp}. Если этого не существует, он выполняет поиск в кэше includelink. Среда IDE сохраняет этот кэш на диск, поэтому среда IDE обучается с течением времени.
204212- После нахождения основного файла TLinkScanner анализирует источник. Он обрабатывает директивы компилятора, такие как директивы include и директивы условной компиляции. Сканеру может быть задан диапазон, например, он может анализировать только интерфейс модулей. Сканер создает *чистый исходник*. Чистый исходный код составляется из всех включаемых файлов, очищенных от директив условной компиляции *else*, которые пропускаются. Он также создает список **ссылок**, которые отображают чистый исходный код в реальные исходные файлы. Чистым исходным кодом теперь является Pascal, не содержащий кода *else*. Примечание: есть также инструменты, предназначенные для сканирования единого исходного кода для всех директив. Эти инструменты создают дерево директив.
205213- После создания очищенного исходника TCodeTool анализирует его и создает дерево TCodeTreeNode. Он также может указать диапазон. Этот анализатор пропускает несколько частей, например члены класса, блоки `begin..end` и списки параметров. Многим инструментам они не нужны. Эти подузлы создаются по запросу. У TCodeTreeNode есть диапазон `StartPos..EndPos`, который является чистой позицией, то есть позицией в очищенном исходнике. Есть только узлы для важных частей. Создание узлов для каждой детали требует больше памяти, чем сам исходник, и \[на практике\] редко востребовано. Существует множество функций, чтобы узнать детали. Например, если функция имеет соглашение о вызовах 'cdecl'.
206214- При поиске идентификатора поиск сохраняет базовые типы, которые он находит, и создает кэши для всех идентификаторов в разделе interface.
207215
208216Каждый уровень имеет свои собственные кэши, которые необходимо проверять и обновлять перед вызовом функции. Многие функции высокого уровня, доступные через CodeToolBoss, делают это автоматически. Для других ответственность за это лежит на \[том, кто их\] вызывает.
209217
210218Пример для:
211219
212220unit1.pas:
213221
214222``` pascal
215223unit Unit1;
216224{$I settings.inc}
217225interface
218226uses
219227 {$IFDEF Flag}
220228 unix,
221229 {$ELSE}
222230 windows,
223231 {$ENDIF}
224232 Classes;
225233```
226234
227235settings.inc:
228236
229237``` pascal
230238{%MainUnit unit1.pas}
231239{$DEFINE Flag}
232240```
233241
234242очищенный исходник:
235243
236244``` pascal
237245unit Unit1;
238246{$I settings.inc}{%MainUnit unit1.pas}
239247{$DEFINE Flag}
240248interface
241249uses
242250 {$IFDEF Flag}
243251 unix,
244252 {$ELSE}{$ENDIF}
245253 Classes;
246254```
247255
248256Подсказка: чтобы было легко разобрать модуль и построить узлы, используйте **CodeToolBoss.Explore**.
249257
250258# CleanPos и CursorPos
251259
252260Есть несколько методов для определения позиции в codetools.
253261
254262Абсолютная позиция 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** для преобразования между ними.
255263
256264# Вставка, удаление, замена - TSourceChangeCache
257265
258266При внесении изменений в исходный код модуля (или его включаемых файлов) вы должны использовать \[функцию\] `CodetoolBoss.SourceChangeCache` вместо непосредственного изменения исходника.
259267
260268- Простое использование: Connect, Replace, Replace, ... Apply. См. ниже.
261269- Вы можете использовать cleanpos, как указано в дереве узлов, ИЛИ вы можете использовать точное положение в файле.
262270- Вы можете использовать Replace для вставки и удаления, что автоматически вызывает события, поэтому подключенные редакторы уведомляются об изменениях.
263271- Он может автоматически вставлять необходимые пробелы, разрывы строк или пустые строки перед или после каждой замены. Например, вы определяете, что впереди должна быть пустая строка. SourceChangeCache проверяет, что вставлено и сколько места уже есть, и вставит необходимое пространство.
264272- Он проверяет, доступен ли для записи замененный/удаленный диапазон.
265273- Вы можете делать множественные замены и контролировать \[процесс\], когда они применяются. Имейте в виду, что вставка кода означает, что проанализированное дерево становится недействительным и нуждается в перестройке.
266274- Множественные замены проверяются на пересечение. Например, вставка в середине удаленного кода выдает ошибку.
267275- Несколько вставок в одном месте добавляются \[по принципу\] FIFO - сначала сверху.
268276- Вы можете объединить несколько функций, изменяя код в одну большую функцию. См. ниже.
269277
270278## Использование
271279
272280SourceChangeCache работает с модулем, поэтому вам нужно получить TCodeTool и отсканировать модуль/include-файл. Например:
273281
274282``` pascal
275283 // Шаг 1: загружаем файл и парсим его
276284 Code:=CodeToolBoss.LoadFile(Filename,false,false);
277285 if Code=nil then
278286 raise Exception.Create('loading failed '+Filename);
279287 if not CodeToolBoss.Explore(Code,Tool,false) then
280288 ...;// parse error ...
281289
282290 // Шаг 2: подключаем SourceChangeCache
283291 CodeToolBoss.SourceChangeCache.MainScanner:=Tool.Scanner;
284292
285293 // Шаг 3: используем Replace для вставки и/или удаления кода
286294 // Первые два параметра - это необходимые пробелы спереди и позади вставки
287295 // FromPos, ToPos определяют удаляемый/заменяемый диапазон в позиции CleanPos.
288296 // NewCode - это строка нового кода. Используем '' для удаления.
289297 if not CodeToolBoss.SourceChangeCache.Replace(gtNone,gtNone,FromPos,ToPos,NewCode) then
290298 exit; // например, исходник [оказался] только для чтения или шаблон Replace удалил место
291299 ...еще немного применяем Replace...
292300
293301 // Шаг 4: Применяем изменения
294302 if not CodeToolBoss.SourceChangeCache.Apply then
295303 exit; // применение было прервано
296304```
297305
298306## BeginUpdate/EndUpdate
299307
300308BeginUpdate/EndUpdate задерживают \[немедленное\] применение \[изменений\]. Это полезно при объединении нескольких функций изменения кода. Например:
301309
302310Вы хотите отсканировать модуль, добавить модуль в секцию uses раздела interface, удалив \[его\] из секции uses раздела implementation. Две функции AddUnitToMainUsesSection и RemoveUnitFromUsesSection используют \[метод\] Apply, изменяя исходник, поэтому вторая функция будет повторно сканировать модуль во второй раз. Но так как эти две функции не зависят друг от друга (они изменяют разные части источника), вы можете объединить их и сделать это за одно сканирование:
303311
304312``` pascal
305313 // Шаг 1: парсим модуль и подключаем SourceChangeCache
306314 if not CodeToolBoss.Explore(Code,Tool,false) then
307315 ...;// ошибка парсинга ...
308316 CodeToolBoss.SourceChangeCache.MainScanner:=Tool.Scanner;
309317
310318 // Шаг 2: задерживаем [применение метода] Apply
311319 CodeToolBoss.SourceChangeCache.BeginUpdate;
312320
313321 // Шаг 3: добавляем модуль в секцию uses раздела interface
314322 // AddUnitToMainUsesSection будет применяться и изменять код
315323 // Из-за BeginUpdate изменение еще не сделано, но сохранено в SourceChangeCache
316324 if not Tool.AddUnitToMainUsesSection('Classes','',CodeToolBoss.SourceChangeCache) then exit;
317325
318326 // Шаг 4: удаляем модуль из секции uses раздела implementation
319327 // Без BeginUpdate RemoveUnitFromUsesSection будет повторно сканировать модуль
320328 if Tool.FindImplementationUsesSection<>nil then
321329 if not Tool.RemoveUnitFromUsesSection(Tool.FindImplementationUsesSection,'Classes',CodeToolBoss.SourceChangeCache) then exit;
322330
323331 // Шаг 5: применяем все изменения
324332 if not CodeToolBoss.SourceChangeCache.EndUpdate then
325333 exit; // применение было прервано
326334```
327335
328336BeginUpdate/EndUpdate работают со счетчиком, поэтому, если вы вызываете BeginUpdate дважды, вам нужно дважды вызывать EndUpdate. Это означает, что вы можете поместить приведенный выше пример в функцию и объединить ее с другой функцией.
329337
330338## Сохранение изменений на диск
331339
332340Вышеуказанные изменения вносятся в буферы кода, и буферы помечаются как измененные. Чтобы сохранить изменения на диске, вы должны вызвать Save для каждого измененного буфера.
333341
334342- Буферы, которые будут изменены в следующем Apply/EndUpdate, находятся в `SourceChangeCache.BuffersToModify` и `BuffersToModifyCount`.
335343- События `SourceChangeCache.OnBeforeApplyChanges/OnAfterApplyChanges` используются CodeToolBoss, который подключает их к собственным `OnBeforeApplyChanges/OnAfterApplyChanges`. Среда Lazarus IDE устанавливает эти события и автоматически открывает измененные файлы в редакторе исходного кода, поэтому все изменения попадают в список отмены synedit.
336344
337345# Подсказки/Советы/Руководства
338346
339347- BuildTree проверяет текущее состояние и будет анализировать \[код\] только при необходимости. Если предыдущий вызов проанализировал интерфейс, и вам снова нужен интерфейс, BuildTree ничего не сделает. Если вам нужен весь модуль, будет проанализирован только раздел implementation. Узлы освобождаются только в том случае, если некоторые файлы изменились на диске или изменились некоторые настройки (исходные макросы). BuildTree не проверяет все файлы при каждом вызове. Вместо этого он использует каталог кеша codetools. Так что, если ничего не изменилось, он вернется очень быстро. Вы должны вызвать его перед любой операцией поиска.
340348- **Не** вызывайте BuildTree **после** операции \[проверки\]. Это пустая трата \[ресурсов\] процессора.
341349- BuildTree вызывает исключение, когда отсутствуют include-файлы или \[имеются\] синтаксические ошибки. Вы должны приложить к своему коду \[следующую конструкцию\]
342350
343351``` pascal
344352try
345353 Tool.BuildTree(lsrEnd);
346354 ... поиск ... замена
347355except
348356 on E: Exception do
349357 CodeToolBoss.HandleException(E);
350358end;
351359```
352360
353361- 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.
354362- После вызова `SourceChangeCache.Replace` (несколько раз) исходники (TCodeBuffers) не изменяются сразу. Вы должны вызвать `SourceChangeCache.Apply`, чтобы изменить исходники. \[Но\] это не сохраняет изменения в файл.
355363
356364# Ссылки
357365
358366- [[Lazarus IDE Tools/ru|Lazarus IDE Tools]] - Учебник по встроенным инструментам стандартной IDE
359367- [[Cody]] - Пакет IDE, добавляющий продвинутые инструменты кода в IDE
360368- [[Extending the IDE/ru|Extending the IDE]] - Как написать свои собственные плагины codetools для IDE.
361369
362370---
363371*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