البنية المعمارية
الطبقات، وخريطة الوحدات، ومراحل التحليل السبع، وتدفق البيانات بين الوحدات
الطبقات
CleanLens مشروع TypeScript فيه محرّك واحد وواجهتان خفيفتان.
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ VS Code extension │ │ CLI │
│ src/extension.ts │ │ src/cli/index.ts │
│ src/views/* │ │ src/cli/format.ts │
└──────────────┬───────────────┘ └──────────────┬───────────────┘
│ analyzeRepository(root, opts) │
└───────────────┬──────────────────┘
▼
┌────────────────────────────────────────────────────────────────┐
│ Core pipeline — src/core/analyzeRepository.ts (no VS Code API) │
├──────────────┬──────────────┬───────────────┬──────────────────┤
│ git/ │ configuration│ analyzers/ │ attribution/ │
│ git commands │ config, rules│ rule checks │ commit replay │
│ + identities │ presets, │ per file │ + fingerprints │
│ │ excludes │ │ │
├──────────────┴──────────────┴───────────────┼──────────────────┤
│ cache/ — per-commit results on disk │ scoring/ — score │
└─────────────────────────────────────────────┴──────────────────┘- فقط
src/extension.tsوsrc/views/*تستوردvscode. كل ما عداهما Node.js عادي، ولهذا يمكن تشغيله من أداة سطر الأوامر ومن الاختبارات. - لا توجد اعتماديات وقت التشغيل سوى
typescript(يستخدمه محلل JS كـ parser، ويدمجه esbuild في الحزمة). كل الوصول إلى Git يتم عبرexecFile("git", …).
خريطة الوحدات
| المجلد | الملف | المسؤولية |
|---|---|---|
src/ | extension.ts | التفعيل، وتسجيل الأوامر، وواجهة التقدّم، وقراءة إعدادات VS Code، وربط التنبيهات المباشرة |
src/core/ | analyzeRepository.ts | خط التحليل المشترك؛ يدمج الإعدادات فوق ملف الإعدادات؛ يبني الذاكرة المؤقتة؛ ويعيد ProjectReport |
src/cli/ | index.ts | تحليل المعاملات، ورموز الخروج، والتعامل مع stdout/stderr |
format.ts | التقرير ← نص / Markdown؛ وفحص --fail-on | |
src/git/ | gitService.ts | "هل هذا مستودع؟"، "هل فيه commits؟"، وgit log لإحصاءات المساهمين |
contributors.ts | يجمع الـ commits في مطورين؛ ويدمج الهويات المكررة | |
commitHistory.ts | يسرد الـ commits غير الدمجية (أحدث N / منذ تاريخ)، من الأقدم للأحدث | |
diffService.ts | أمر git diff واحد لكل commit ← الملفات المتغيرة، ومدى الأسطر، ومعرّفات الـ blobs؛ وgit cat-file --batch لقراءة الـ blobs | |
blameService.ts | محلل لمخرجات git blame --line-porcelain. قديم (من محرّك blame السابق)؛ ما زال مختبَراً، ولا يستخدمه خط التحليل | |
src/configuration/ | types.ts | أنواع الإعدادات، ومعرّفات القواعد الأربع عشرة وعناوينها وفئاتها، وأسماء الملفات |
configValidator.ts | التحقق من بنية .clean-code-tracker.json | |
configLoader.ts | تحميل الإعدادات (أو الإعداد المسبق الافتراضي)، ودمج التخصيص المحلي، وكتابة ملف إعدادات جديد | |
presets.ts | الإعدادات المسبقة الأربعة؛ واكتشاف الإعداد المناسب تلقائياً | |
excludes.ts | الاستثناءات المدمجة؛ وقراءة .gitignore / .gitattributes؛ وكشف ترويسة الملفات المولَّدة | |
src/analyzers/ | fileScanner.ts | استعراض المجلدات لفحص HEAD |
glob.ts | تحويل glob بسيط إلى RegExp، وExcludeMatcher | |
jsAnalyzer.ts | قواعد مبنية على شجرة AST لـ JS/TS (واجهة مترجم TypeScript) | |
pyAnalyzer.ts | قواعد مبنية على الأسطر والمسافة البادئة لـ Python | |
duplicateCode.ts | كشف الكتل المكررة بنافذة منزلقة | |
secrets.ts، names.ts | قواعد تقديرية مشتركة للأسرار والأسماء غير الواضحة | |
model.ts | RawFinding ← Violation؛ ودوال مساعدة لقراءة تفعيل القاعدة وحدّها وخياراتها | |
runAnalyzers.ts | تنسيق فحص HEAD؛ واختيار المحلل حسب امتداد الملف | |
analyzeRevision.ts | تحليل نسخة واحدة من ملف (blob) وإعطاء كل مخالفة بصمة | |
src/attribution/ | commitAttribution.ts | يمر على الـ commits، ويقارن قبل/بعد، ويصنّف كل مخالفة |
attributeReport.ts | يدمج مخالفات HEAD مع نتائج الـ commits؛ ويقيّم المطورين | |
fingerprint.ts | دالة hash من نوع FNV-1a؛ والبصمة الثابتة للمخالفة | |
ownership.ts | خريطة البريد الإلكتروني ← معرّف المطوّر (+ دوال blame القديمة) | |
src/scoring/ | scoringConfig.ts | كل ثابت قابل للضبط: الأوزان، والمقاييس، والقيمة المسبقة، والحدود، وENGINE_VERSION |
cleanCodeScore.ts | معادلة الدرجة | |
src/cache/ | analysisCache.ts | ذاكرة JSON المؤقتة لكل commit + بصمة الإعدادات |
src/types/ | index.ts | Severity وViolation وDeveloper وProjectReport والحالات |
src/views/ | treeProviders.ts | أشجار الشريط الجانبي + ReportStore |
dashboardPanel.ts | دورة حياة لوحة الـ webview ورسائلها | |
dashboardHtml.ts | توليد HTML/CSS/JS خالص للوحة المعلومات | |
diagnostics.ts | تنبيهات المحرر: تغذية التقرير الكامل والتغذية المباشرة |
خط التحليل خطوة بخطوة
الدالة analyzeRepository(root, opts) في src/core/analyzeRepository.ts:
1. Git checks git rev-parse --is-inside-work-tree, git rev-parse HEAD
2. Config loadConfig() → applySettings(VS Code / CLI overrides)
readRepoAttributes() (.gitignore, .gitattributes)
mergedExcludeGlobs(), resolveScoring(), analysisConfigHash()
3. Developers git log --no-merges → aggregateContributors() → toDevelopers()
4. HEAD scan analyzeProject(): walk files → analyzer per file → duplicates
→ sorted Violation[]
5. Commit walk attributeCommits(): newest N commits, oldest first,
12 in parallel, each: diff → blobs → analyze before/after
→ introduced / fixed / existing
6. Merge + score attributeReport(): fingerprint every HEAD violation, look up
its origin, set status/confidence/developer; compute the
project prior; score every developer
7. Display extension: tree views, dashboard, diagnostics
CLI: text / Markdown / JSON + exit codeالمراحل:
- فحوصات Git: هل المجلد مستودع؟ وهل فيه commit؟
- الإعدادات: تحميل ملف الإعدادات ودمج إعدادات VS Code أو خيارات سطر الأوامر فوقه، وقراءة
.gitignoreو.gitattributes، وبناء قائمة الاستثناءات وثوابت التقييم وبصمة الإعدادات. - المطورون: قراءة سجل Git وتجميع الـ commits في مطورين.
- فحص HEAD: تحليل الملفات الحالية وإنتاج قائمة المخالفات مرتبة.
- مرور الـ commits: أحدث N commit من الأقدم للأحدث، 12 بالتوازي؛ لكل واحد: diff ← blobs ← تحليل قبل/بعد ← أُدخلت / أُصلحت / موجودة سابقاً.
- الدمج والتقييم: بصمة لكل مخالفة في HEAD، والبحث عن أصلها، وتحديد حالتها وثقتها ومطوّرها؛ ثم حساب متوسط المشروع وتقييم كل مطوّر.
- العرض: في الإضافة: الأشجار ولوحة المعلومات والتنبيهات؛ وفي سطر الأوامر: نص / Markdown / JSON + رمز الخروج.
المراحل 1–6 متطابقة في الواجهتين. الذي يختلف هو الخيارات فقط:
| الخيار | الإضافة | أداة سطر الأوامر |
|---|---|---|
config | يُحمَّل من المستودع | يُحمَّل من المستودع، أو --preset |
settings | من إعدادات VS Code (cleanlens.*) | من --max-commits و--full-history و--since |
cacheDir | context.globalStorageUri | <os tmpdir>/cleanlens-cache |
cache | cleanlens.cache.enabled | يُعطَّل بـ --no-cache |
signal | زر Cancel في إشعار التقدّم | لا يوجد |
الأخطاء المتوقعة
يُرمى AnalysisError في المشاكل التي يستطيع المستخدم إصلاحها: المجلد ليس مستودع Git، ولا توجد commits، وملف الإعدادات غير صالح. الإضافة تعرضه كرسالة خطأ، وأداة سطر الأوامر تطبع error: … وتخرج بالرمز 2. أي استثناء آخر يعني وجود خلل في الكود.
تدفق البيانات والأنواع
RawFinding ──toViolation()──▶ Violation (severity, category, weight, id)
│
analyzeRevision() │ fingerprintFor()
▼
RevisionViolation (+fingerprint) ─▶ CommitContribution (per commit, cached)
│
attributeCommits() aggregates
▼
DeveloperAttribution (per developer) + origins (fingerprint → commit)
│
attributeReport()
▼
ProjectReport { developers[], violations[] }تعريفات الأنواع موجودة في src/types/index.ts وsrc/configuration/types.ts. وصيغة التقرير موثّقة حقلاً بحقل في 14 — بنية التقرير.
تحليلان لغرضين مختلفين
هذه أهم نقطة في التصميم يجب فهمها:
| فحص HEAD (المرحلة 4) | مرور الـ commits (المرحلة 5) | |
|---|---|---|
| المدخل | الملفات الموجودة على القرص الآن | الـ blobs من سجل Git |
| المخرج | قائمة المخالفات التي تُعرض لك | من أدخل / أصلح ماذا، والأسطر المحللة |
| كشف التكرار | عبر كل الملفات | داخل كل ملف فقط |
| النطاق | كل ملف قابل للتحليل | فقط الملفات التي غيّرتها الـ commits المحللة |
المرحلة 6 تربط بينهما بالبصمات. مخالفة في HEAD أُدخلت بصمتها أثناء مرور الـ commits تُنسب إلى كاتب ذلك الـ commit. ومخالفة في HEAD لم تظهر أبداً أثناء المرور هي أقدم من نافذة التحليل ← existing.
مخرجات البناء
يجمّع esbuild ملفين مستقلين:
dist/extension.js— نقطة الدخولsrc/extension.ts، ويبقىvscodeخارج الحزمة.dist/cli.js— نقطة الدخولsrc/cli/index.ts، مع سطر#!/usr/bin/env nodeفي البداية؛ ويُعرض كأمرcleanlens.
انظر 15 — دليل التطوير لأوامر البناء.