
# بحث AST المفهرس

بحث AST المفهرس هو النسخة ذات الذاكرة المؤقتة المُحمّاة من [بحث AST](https://greph.inline0.dev/ar/docs/modes/ast). يستخرج الاستدعاء الأول حقائق على مستوى العقد (أسماء الاستدعاءات، وإنشاء الكائنات، وإعلانات الفئات، وإعلانات الأساليب) ويخزنها على القرص؛ أما الاستدعاءات اللاحقة فتستخدم المخزن لتخطي الملفات التي لا يمكن أن تحتوي بوضوح على مطابقة بنيوية. ثم يعيد المطابق التحقق من المرشحين بمقارنتهم بالمصدر.

يتوفر فهرس الحقائق ضمن الأمر الفرعي `greph-index ast-index` CLI وطرائق الواجهة `Greph::buildAstIndex()` / `Greph::searchAstIndexed()`. كما يشارك في مسارات العمل المُحمّاة متعددة الفهارس والمجموعات المدعومة بالبيانات الوصفية.

## إنشاء الفهرس

```bash
# Full build at the current directory
./vendor/bin/greph-index ast-index build .

# Full build at an explicit root
./vendor/bin/greph-index ast-index build path/to/repo

# Use a non-default index directory
./vendor/bin/greph-index ast-index build . --index-dir /tmp/greph-ast-index

# Build a mutable overlay that can refresh cheaply on demand
./vendor/bin/greph-index ast-index build . \
  --lifecycle opportunistic-refresh \
  --auto-refresh-max-files 32 \
  --auto-refresh-max-bytes 1048576
```

يُخزّن فهرس الحقائق افتراضيًا في `<root>/.greph-ast-index/`.

يعرض الإنشاء الناجح ملخصًا في سطر واحد:

```text
Built AST index for 2547 files in .greph-ast-index (84931 fact rows, +2547 ~0 -0 =0)
```

تتتبّع العدادات الأربعة الملفات المضافة والمحدّثة والمحذوفة وغير المتغيرة منذ آخر إنشاء للفهرس.

## تحديث الفهرس

```bash
./vendor/bin/greph-index ast-index refresh .
```

يعيد `refresh` اجتياز الجذر المفهرس، ويعيد تحليل الملفات التي تغيّرت، ويعيد كتابة صفوف الحقائق التي تغيّرت فقط. ويستخدم الإخراج العدادات الأربعة نفسها المستخدمة في فهرس النصوص.

تعمل ملفات تعريف دورة الحياة بالطريقة نفسها المستخدمة مع فهارس النصوص المُحمّاة:

- `static`: لا يتحقق من حداثة البيانات أو يغيّرها تلقائيًا مطلقًا
- `manual-refresh`: يعرض حالة التقادم في `stats`، لكنه لا يحدّث أثناء البحث مطلقًا
- `opportunistic-refresh`: يحدّث أثناء البحث فقط عندما تكون مجموعة الملفات المتغيرة صغيرة بما يكفي
- `strict-stale-check`: يرفض عمليات البحث عن البيانات المتقادمة بدلًا من تحديثها

## الاستعلام في الفهرس

```bash
./vendor/bin/greph-index ast-index search 'new $CLASS()' src
./vendor/bin/greph-index ast-index search '$obj->$method($$$ARGS)' src
./vendor/bin/greph-index ast-index search --json 'array($$$ITEMS)' src
./vendor/bin/greph-index ast-index search -l 'array($$$ITEMS)' src
./vendor/bin/greph-index ast-index search --trace-plan 'new $CLASS()' src
```

صياغة المتغيرات الوصفية مطابقة لصياغتها في بحث AST الأصلي. راجع [الأوضاع / بحث AST](https://greph.inline0.dev/ar/docs/modes/ast) للاطلاع على القواعد كاملة.

### الخيارات

| الخيار | المعنى |
|---|---|
| `--lang NAME` | لغة AST. الافتراضية: `php` |
| `-j N`، `--jobs N` | عدد العاملين المتوازيين |
| `-l`، `--files-with-matches` | سرد الملفات المطابقة فقط |
| `--glob GLOB` | تضمين الملفات التي تطابق مساراتها GLOB فقط |
| `--type NAME` / `--type-not NAME` | تصفية نوع الملف |
| `--json` | إصدار مخرجات JSON |
| `--no-ignore` | تجاهل `.gitignore` و`.grephignore` |
| `--hidden` | تضمين الملفات المخفية |
| `--strict-parse` | الإخفاق عند أخطاء التحليل بدلًا من تخطيها |
| `--fallback MODE` | سلوك الفهرس المفقود: `fail` (الافتراضي) أو `scan` |
| `--index-dir DIR` | استخدام مجلد فهرس غير افتراضي |
| `--trace-plan` | إصدار تشخيصات مخطِّط AST المُحمّى إلى `stderr` |
| `--show-index-origin` | إضافة تسمية مدخل الفهرس المطابق إلى بداية الإخراج في وضع الفهارس المتعددة أو المجموعات |

### الرجوع عند غياب الفهرس

افتراضيًا، يُصدر `ast-index search` خطأً عند عدم وجود فهرس في الموقع المطلوب. مرّر `--fallback scan` للرجوع إلى فحص AST أصلي. وهذا الخيار مناسب للأدوات التي تريد استخدام البحث المفهرس عند توفره، مع استمرار عرض النتائج إذا لم يُنشأ الفهرس بعد.

```bash
./vendor/bin/greph-index ast-index search --fallback scan 'new $CLASS()' src
```

### البحث عبر فهارس متعددة

يمكنك البحث في عدة فهارس AST مُحمّاة بأمر واحد بتكرار `--index-dir`. وهذا مفيد لتخطيطات مثل WordPress مع إضافة مكوّن إضافي أو سمة.

```bash
./vendor/bin/greph-index ast-index search \
  --index-dir ../wordpress/.greph-ast-index \
  --index-dir ./.greph-ast-index \
  --show-index-origin \
  'new $CLASS()' .
```

عند تفعيل `--show-index-origin`، تُسبق النتائج باسم مدخل الفهرس المُحمّى المطابق، لتتمكن من معرفة الجذر الذي أظهر النتيجة.

### مجموعات الفهارس المدعومة بالبيانات الوصفية

لإعدادات مُحمّاة مستقرة، عرّف ملفًا للبيانات الوصفية ودع `greph-index set` يعمل على الفهارس المجمّعة:

```bash
./vendor/bin/greph-index set build
./vendor/bin/greph-index set stats --mode ast-index --dry-refresh
./vendor/bin/greph-index set search --mode ast-index --show-index-origin 'new $CLASS()' .
```

تستخدم الأوامر الفرعية للمجموعة معالجة دورة الحياة وفحوصات التقادم وتشخيصات المخطِّط نفسها المستخدمة عند تشغيل `ast-index` مباشرةً.

### تشخيصات المخطِّط

يعرض `--trace-plan` كيفية تضييق Greph نطاق الاستعلام قبل تشغيل المطابق الكامل. وبالنسبة إلى `ast-index`، يشمل ذلك عادةً:

- توقيع الحقائق التقريبي المستخرج من النمط
- عدد الفهارس المُحمّاة التي جرى البحث فيها
- عدد الملفات التي استبعدها مرشح الحقائق
- عدد الملفات المرشحة التي أُعيد تحليلها للتحقق البنيوي الدقيق

## ما الذي يخزنه الفهرس

يسجل مستخرج حقائق AST صفًا لكل عقدة «مهمة» في كل ملف مفهرس. وتشمل أنواع الحقائق البنى التي تستهدفها أنماط AST عادةً:

- استدعاءات الدوال والأساليب (حسب الاسم المستدعى)
- إنشاء كائنات الفئات (حسب اسم الفئة)
- إعلانات الفئات والواجهات والسمات والتعدادات (حسب الاسم)
- إعلانات الدوال (حسب الاسم)
- إعلانات الأساليب (حسب الاسم ومستوى الظهور)
- عبارات الاستيراد

عند وصول استعلام، يحوّل `Greph\Ast\AstFactQuery` نمط البحث إلى توقيع حقائق تقريبي (مثلًا: «يجب أن يتضمن `new` من أي فئة») ويبحث في مخزن الحقائق عن الملفات المطابقة. ثم يعيد تحليل الملفات التي تجتاز المطابقة ويقارنها بالنمط الكامل.

هذا يعني أن فهرس الحقائق مرشح أولي، وليس مخزنًا للمطابقات كاملة الدقة. تظل خطوة المطابقة تحلل المصدر، لذا تبقى الدقة البنيوية مطابقة لبحث AST الأصلي؛ والاختلاف الوحيد هو صغر مجموعة المرشحين.

## متى تستخدمه

يُعد وضع AST المفهرس مناسبًا عندما:

- تُجري الاستعلامات البنيوية نفسها على قاعدة الأكواد نفسها مرارًا.
- تستهدف الأنماط أشكالًا يمكن تحديدها (اسم الاستدعاء أو اسم الفئة أو نوع الإعلان) يخزنها مستخرج الحقائق.
- تريد تقليل زمن الاستجابة مقارنةً بإعادة تحليل كل ملف.

بالنسبة إلى الأنماط التي لا تظهر ميزتها المميزة في مجموعة الحقائق (مثل التعبيرات المتداخلة المعقدة التي لا رأس معروفًا لها)، يكون [وضع AST المخزّن مؤقتًا](https://greph.inline0.dev/ar/docs/indexed/cache) عادةً أنسب، لأنه يتخطى خطوة التحليل بالكامل دون الاعتماد على توقيع تقريبي.

## الاستخدام البرمجي

```php
use Greph\Greph;
use Greph\Ast\AstSearchOptions;
use Greph\Index\IndexLifecycleProfile;

Greph::buildAstIndex('.', lifecycle: IndexLifecycleProfile::OpportunisticRefresh);

$matches = Greph::searchAstIndexed(
    'new $CLASS()',
    'src',
    new AstSearchOptions(jobs: 4, tracePlan: true),
);
```

يقبل `searchAstIndexed` وسيطات `AstSearchOptions` نفسها التي يقبلها بحث AST الأصلي، ويعيد بنية `list<AstMatch>` نفسها. لمسارات العمل متعددة الفهارس أو المدعومة بالبيانات الوصفية، استخدم `searchAstIndexedMany(...)` و`searchAstIndexedSet(...)`.
