طبقة التحليل resolve.ts
تحليل المراجع ودمج الوضع الداكن.
دالة resolveTokens(files: LoadedTokenFile[]): ResolveResult هي الدالة الأساسية، وتأتي ثلاثة أجزاء:
القيمة المُعادة
Section titled “القيمة المُعادة”interface ResolveResult { tokenSet: TokenSet // مجموعة رموز الوضع الفاتح + جدول تغطية الوضع الداكن orphanDarkPaths: string[] // المسارات الداكنة اليتيمة (لتقارير verify) refMap: Map<string, string> // path ← سلسلة ref الأصلية (المفاتيح الداكنة تحمل بادئة dark:)}الجزء الأول: طي الوضع الفاتح
Section titled “الجزء الأول: طي الوضع الفاتح”دمج flat لجميع الملفات غير الداكنة في rawMap واحد:
if (rawMap.has(path)) throw new Error(`تعريف مكرر لمسار الرمز: ${path} (الملف ${file.fileName})`)يحمل كل سجل ثلاث قيم:
| الحقل | المعنى |
|---|---|
token |
ResolvedToken قيد التجميع (يأخذ النوع أولًا من raw.type ?? file.defaultType كتراجع) |
raw / ref |
القيمة الأصلية وسلسلة المرجع |
ownType |
النوع الذي أعلنه الرمز بنفسه، مخصص للتمييز بين «ما أعلنه الرمز» و«الافتراضي على مستوى الملف» |
ownType هو مفتاح أولويات الأنواع ذات الطبقات الثلاث: بعد عودة تحليل ref، فقط عندما يكون ownType === undefined يُعتمد نوع الهدف المُشار إليه.
الجزء الثاني: تحليل ref
Section titled “الجزء الثاني: تحليل ref”الدالة المضمَّنة resolveRef(path, chain): { value, type? }:
rawMap.get(path)غير موجود ← يُطلقالرمز المُشار إليه غير موجود: <path>- الهدف نفسه هو ref ← تكرار
resolveRef(entry.ref, [...chain, path]) chain.includes(path)← يُطلقتم اكتشاف حلقة في مراجع الرموز: a -> b -> a- الوصول إلى قيمة حرفية ← تعاد
{ value, type }
الحلقة الرئيسية لكل سجل يحتوي على ref:
refMap.set(path, entry.ref) // تسجيل علاقة المرجعconst resolved = resolveRef(entry.ref, [path])entry.token.value = resolved.value // الخَبز إلى قيمة حرفيةentry.token.refChain = [entry.ref] // تسجيل سلسلة المرجعif (entry.ownType === undefined && resolved.type !== undefined) { entry.token.type = resolved.type // النوع يتبع المصدر الأصلي}أخيرًا:
if (entry.token.type === undefined) { throw new Error(`الرمز ${path} يفتقر إلى النوع (لا type ذاتي ولا $type على مستوى الملف)`)}assertTypedValue(entry.token.type, value) // تحقق دلاليتُرتَّب النتائج حسب path معجميًا، ويُبنى فهرس byPath في الوقت نفسه.
الجزء الثالث: تغطية الوضع الداكن
Section titled “الجزء الثالث: تغطية الوضع الداكن”لا يُعلِن ملف الوضع الداكن سوى المفاتيح التي تحتاج تغطية.
عرض مساحة أسماء الوضع الداكن: يُعاد طي flat لجميع ملفات الوضع الداكن مرة أخرى إلى darkRawMap (path ← { value, ref }).
الدالة المضمَّنة resolveDarkRef(path, chain): TokenValue — تحليل مراجع الوضع الداكن بالأقرب:
| الحالة | السلوك |
|---|---|
الهدف في darkRawMap وهو ref |
تتبع السلسلة بشكل متداخل داخل مساحة أسماء الوضع الداكن (فقط عندما يشير الداكن إلى الداكن تُؤخذ القيمة من النمط نفسه)، مع الكشف عن الحلقات كذلك |
الهدف في darkRawMap وهو قيمة حرفية |
إعادة قيمة الوضع الداكن |
الهدف ليس في darkRawMap |
التراجع إلى مساحة أسماء الوضع الفاتح أيا كان resolveRef(path, chain).value |
المرور على سجلات الوضع الداكن:
if (raw.ref) { // يجب أن يكون الهدف موجودًا في أحد هذه: byPath / rawMap / darkRawMap if (!byPath.has(raw.ref) && !rawMap.has(raw.ref) && !darkRawMap.has(raw.ref)) { throw new Error(`مرجع الرمز الداكن ${path} غير موجود: ${raw.ref}`) } value = resolveDarkRef(raw.ref, [path]) refMap.set(`dark:${path}`, raw.ref) // المفاتيح الداكنة تحمل البادئة}const type = raw.type ?? byPath.get(path)?.typeif (!type) { orphanDarkPaths.push(path); continue } // نقص النوع ← تخطي هذا المفتاحassertTypedValue(type, value)if (!byPath.has(path)) orphanDarkPaths.push(path) // يتيم ← يبقى مكتوبًا في جدول التغطيةdark.set(path, value)المسارات الداكنة اليتيمة
Section titled “المسارات الداكنة اليتيمة”حالتان شاذتان لا توقفان codegen، بل تُسجَّلان في orphanDarkPaths ويُبلَّغ عنهما عبر pnpm verify:tokens:
- مفتاح داكن يفتقر إلى النوع (لا يملك نوعًا ذاتيًا، ولا يوجد مفتاح مماثل في مجموعة الوضع الفاتح يرث منه) ← تخطي المفتاح، دون كتابته في جدول التغطية
- مفتاح داكن غير موجود في مجموعة الوضع الفاتح (يتيم) ← يبقى مكتوبًا في جدول التغطية، لكن يُبلَّغ عنه
راجع دمج الوضع الداكن.
كيف تستهلك الأطراف dark
Section titled “كيف تستهلك الأطراف dark”dark هو Map<path, TokenValue> مسطح، ويقرر كل هدف كيفية إصداره (Kotlin / Swift / ArkTS تستخدم مساحات أسماء LhDarkTokens مستقلة، وC يستخدم إعادة تعريف الماكرو بالاسم نفسه). راجع الأهداف الخمسة.
Copyright © 2024-2026 FengMo WenXue