
lintpack هي أداة مفيدة لبناء اللنتر (المحللون الاستاتيكيون) ، والتي تتم كتابتها باستخدام واجهة برمجة التطبيقات المتوفرة. بناءً على ذلك ، يتم الآن إعادة كتابة المحلل الثابت للنقد ، المألوف لدى البعض.
اليوم lintpack
بمزيد من التفصيل ما lintpack
من وجهة نظر المستخدم.
في البداية كان الناقد ...
بدأ الناقد كمشروع تجريبي كان بمثابة وضع حماية للنماذج الأولية لأي أفكار تحليل ثابتة لـ Go.
كانت المفاجأة السارة أن بعض الأشخاص أرسلوا تطبيقات للكشف عن مشاكل مختلفة في الكود. كان كل شيء تحت السيطرة حتى بدأ الدين التقني في التراكم ، والذي لم يكن هناك من يستغني عنه عمليا. جاء الناس ، وأضافوا التحقق ، ثم اختفوا. ثم من الذي عليه تصحيح الأخطاء وتعديل التنفيذ؟
كان من الأحداث الهامة اقتراح إضافة عمليات التحقق التي تتطلب تكوينًا إضافيًا ، أي تلك التي تعتمد على الترتيبات المحلية للمشروع. أحد الأمثلة هو الكشف عن وجود رأس حقوق طبع ونشر في ملف (رأس ترخيص) باستخدام قالب خاص أو حظر استيراد بعض الحزم مع اقتراح بديل معين.
الصعوبة الأخرى كانت التمدد. ليس من المناسب للجميع إرسال رمزهم إلى مستودع شخص آخر. أراد البعض ربط الشيكات ديناميكيًا بحيث لا يحتاجون إلى تعديل رموز مصدر go-critic
.
الخلاصة ، فيما يلي المشاكل التي تقف في طريق تطوير go-critic
:
- حمولة من التعقيد. الكثير من الدعم ، وجود رمز بدون مالك.
- جودة متوسطة منخفضة. يعني
experimental
"جاهز تقريبًا للاستخدام" و "الأفضل ألا يعمل على الإطلاق". - في بعض الأحيان يكون من الصعب تحديد ما إذا كان سيتم تضمين التحقق في
go-critic
، ورفضها يتعارض مع فلسفة التصميم الأصلية. - رأى الناس مختلفين
go-critic
مختلف. أراد معظمهم الحصول عليه باعتباره gometalinter
، والذي يأتي مع gometalinter
.
من أجل الحد من عدد التناقضات والتفسيرات غير المتسقة للمشروع بطريقة ما ، تم كتابة بيان .
إذا كنت تريد سياقًا تاريخيًا إضافيًا ومزيدًا من التفكير في تصنيف المحللات الثابتة ، فيمكنك الاستماع إلى تسجيل GoCritic ، وهو محلل ثابت جديد لـ Go . في تلك اللحظة ، لم تكن lintpack موجودة بعد ، ولكن بعض الأفكار ولدت في ذلك اليوم ، بعد التقرير.
ولكن ماذا لو لم نكن بحاجة إلى تخزين جميع الشيكات في مستودع واحد؟

يتكون go-critic
من مكونين رئيسيين:
- تنفيذ الشيكات بأنفسهم.
- برنامج يقوم بتنزيل حزم التحقق من الصحة Go ويقوم بتشغيل عمليات التحقق منها.
هدفنا: أن نكون قادرين على تخزين الشيكات للليتر في مستودعات مختلفة وجمعها معًا عند الضرورة.
lintpack يفعل ذلك فقط. وهي تحدد الوظائف التي تسمح لك بوصف الشيكات الخاصة بك بطريقة يمكنك بعد ذلك تشغيلها من خلال اللتر الذي تم إنشاؤه.
تسمى الحزم التي يتم تنفيذها باستخدام lintpack
كإطار عمل lintpack
متوافقة مع lintpack
أو متوافقة مع lintpack
.
إذا تم تنفيذ go-critic
على أساس lintpack
، يمكن تقسيم جميع الشيكات إلى عدة مستودعات. قد يكون أحد خيارات الفصل ما يلي:
- المجموعة الرئيسية حيث تحصل جميع الشيكات المستقرة والمدعومة.
- ساهم بمستودع حيث يكون الكود إما تجريبيًا جدًا أو يفتقر إلى مشرف.
- فحوصات قابلة للتخصيص لمشروع محدد.
النقطة الأولى ذات أهمية خاصة فيما يتعلق بدمج الناقد في golangci-lint .
إذا بقيت على مستوى go-critic
، فلن يتغير شيء تقريبًا للمستخدمين. lintpack
متطابق تقريبًا ، في حين أن golangci-lint
جميع تفاصيل التنفيذ المختلفة.
لكن شيئاً ما تغير. إذا تم إنشاء lintpack
جديدة على أساس lintpack
، فسيكون لديك مجموعة أكثر ثراء من التشخيصات الجاهزة لتوليد اللتر. تخيل للحظة أن الأمر كذلك ، وهناك أكثر من 10 مجموعات مختلفة من الشيكات في العالم.
بداية سريعة

للبدء ، تحتاج إلى تثبيت lintpack
نفسه:
قم بإنشاء linter باستخدام حزمة الاختبار من lintpack
:
lintpack build -o mylinter github.com/go-lintpack/lintpack/checkers
تتضمن المجموعة panicNil
، التي تجد panic(nil)
في التعليمات البرمجية وتطلب استبدالها بشيء مميز ، وإلا لن يتمكن recover()
من معرفة ما إذا كان panic
تم استدعاؤه بحجة nil
، أو لم يكن هناك ذعر على الإطلاق.
مثال مع ذعر (لا شيء)
يحاول الرمز أدناه وصف القيمة التي تم الحصول عليها من recover()
:
r := recover() fmt.Printf("%T, %v\n", r, r)
ستكون النتيجة مماثلة panic(nil)
التي لا panic(nil)
.
مثال على السلوك الموصوف .
يمكنك بدء اللنتر على ملفات منفصلة ، بحجج من النوع ./...
أو الحزم (حسب مسار الاستيراد).
./mylinter check bytes $GOROOT/src/bytes/buffer_test.go:276:3: panicNil: panic(nil) calls are discouraged
بشكل افتراضي ، يستجيب هذا الفحص أيضًا panic(interface{}(nil))
. لتجاوز هذا السلوك ، قم بتعيين skipNilEfaceLit
على true
. يمكنك القيام بذلك من خلال سطر الأوامر:
$mylinter check -@panicNil.skipNilEfaceLit=true ./panicNil/ ./panicNil/positive_tests.go:5:3: panicNil: panic(nil) calls are discouraged
استخدام ل cmd / lintpack و linter ولدت
lintpack
كل من lintpack
و lintpack
الناتج الوسيطة الأولى لتحديد أمر فرعي. يمكن الحصول على قائمة الأوامر الفرعية المتاحة وأمثلة على إطلاقها عن طريق استدعاء الأداة المساعدة بدون وسيطات.
lintpack not enough arguments, expected sub-command name Supported sub-commands: build - build linter from made of lintpack-compatible packages $ lintpack build -help $ lintpack build -o gocritic github.com/go-critic/checkers $ lintpack build -linter.version=v1.0.0 . version - print lintpack version $ lintpack version
لنفترض أننا أطلقنا على اسم gocritic
تم إنشاؤه باسم gocritic
:
./gocritic not enough arguments, expected sub-command name Supported sub-commands: check - run linter over specified targets $ linter check -help $ linter check -disableTags=none strings bytes $ linter check -enableTags=diagnostic ./... version - print linter version $ linter version doc - get installed checkers documentation $ linter doc -help $ linter doc $ linter doc checkerName
علامة -help
متاحة لبعض الأوامر الفرعية ، والتي توفر معلومات إضافية (أقوم بقص بعض الخطوط العريضة جدًا):
./gocritic check -help
توثيق الشيكات المثبتة
الجواب على السؤال "كيف تعرف عن معلمة skipNilEfaceLit؟" - قراءة دليل الهوى (RTFM)!
جميع الوثائق حول الشيكات المثبتة داخل mylinter
. هذه الوثائق متاحة من خلال الأمر الفرعي doc
:
مثل دعم القوالب في go list -f
، يمكنك تمرير سطر قالب مسؤول عن تنسيق الإخراج للوثائق ، والذي يمكن أن يكون مفيدًا عند كتابة مستندات تخفيض السعر.
أين تبحث عن شيكات التثبيت؟
لتبسيط البحث عن مجموعات lintpack
المفيدة ، هناك قائمة مركزية من الحزم المتوافقة مع lintpack
: https://go-lintpack.imtqy.com/ .
إليك بعض القائمة:
يتم تحديث هذه القائمة بشكل دوري وهي مفتوحة لطلبات الإضافة. يمكن استخدام أي من هذه الحزم لإنشاء اللتر.
يقوم الأمر أدناه بإنشاء لنتر يحتوي على كافة عمليات التحقق من القائمة أعلاه:
يتضمن lintpack build
جميع الفحوصات في مرحلة التجميع ، ويمكن وضع lintpack build
الناتج في بيئة لا توجد فيها رموز مصدر لتنفيذ التشخيصات المثبتة ، وكل شيء على النحو المعتاد مع الربط الثابت.
مرفق الحزمة الديناميكية
بالإضافة إلى التجميع الثابت ، من الممكن تحميل الإضافات التي توفر فحوصات إضافية.
تكمن الخصوصية في أن تطبيق المدقق لا يعرف ما إذا كان سيتم استخدامه لتجميع ثابت أو سيتم تحميله كمكون إضافي. مطلوب أي تغييرات على الرمز.
لنفترض أننا نريد إضافة panicNil
إلى panicNil
، لكننا لسنا قادرين على إعادة بنائه من جميع المصادر التي تم استخدامها أثناء التجميع الأول.
- قم
linterPlugin.go
:
package main
- بناء مكتبة ديناميكية:
go build -buildmode=plugin -o linterPlugin.so linterPlugin.go
- قم بتشغيل
-pluginPath
مع المعلمة -pluginPath
:
./linter check -pluginPath=linterPlugin.so bytes
تحذير: يتم تنفيذ دعم الوحدات الديناميكية من خلال حزمة مكون إضافي لا تعمل على Windows.
يمكن أن تساعدك علامة -verbose
معرفة أي فحص قيد التشغيل أو إيقاف تشغيله ، والأهم من ذلك أنها ستعرض الفلتر الذي عطّل الفحص.
مثال مع -verbose
لاحظ أنه panicNil
عرض panicNil
في قائمة الاختبارات المضمنة. إذا قمنا بإزالة الوسيطة -pluginPath ، فسوف تتوقف عن صحتها.
./linter check -verbose -pluginPath=./linterPlugin.so bytes debug: appendCombine: disabled by tags (-disableTags) debug: boolExprSimplify: disabled by tags (-disableTags) debug: builtinShadow: disabled by tags (-disableTags) debug: commentedOutCode: disabled by tags (-disableTags) debug: deprecatedComment: disabled by tags (-disableTags) debug: docStub: disabled by tags (-disableTags) debug: emptyFallthrough: disabled by tags (-disableTags) debug: hugeParam: disabled by tags (-disableTags) debug: importShadow: disabled by tags (-disableTags) debug: indexAlloc: disabled by tags (-disableTags) debug: methodExprCall: disabled by tags (-disableTags) debug: nilValReturn: disabled by tags (-disableTags) debug: paramTypeCombine: disabled by tags (-disableTags) debug: rangeExprCopy: disabled by tags (-disableTags) debug: rangeValCopy: disabled by tags (-disableTags) debug: sloppyReassign: disabled by tags (-disableTags) debug: typeUnparen: disabled by tags (-disableTags) debug: unlabelStmt: disabled by tags (-disableTags) debug: wrapperFunc: disabled by tags (-disableTags) debug: appendAssign is enabled debug: assignOp is enabled debug: captLocal is enabled debug: caseOrder is enabled debug: defaultCaseOrder is enabled debug: dupArg is enabled debug: dupBranchBody is enabled debug: dupCase is enabled debug: dupSubExpr is enabled debug: elseif is enabled debug: flagDeref is enabled debug: ifElseChain is enabled debug: panicNil is enabled debug: regexpMust is enabled debug: singleCaseSwitch is enabled debug: sloppyLen is enabled debug: switchTrue is enabled debug: typeSwitchVar is enabled debug: underef is enabled debug: unlambda is enabled debug: unslice is enabled
من أجل تجنب الارتباك ، يجدر وصف الاختلافات الرئيسية بين المشاريع.
gometalinter و golangci-lint يدمجان في الأساس موادًا أخرى ، غالبًا ما يتم تنفيذها بشكل مختلف تمامًا ، توفر إمكانية وصول مريحة إليها. تستهدف المستخدمين النهائيين الذين سيستخدمون أجهزة تحليل ثابتة.
يبسط lintpack إنشاء عتبات جديدة ، ويوفر إطار عمل يجعل الحزم المختلفة ، التي يتم تنفيذها على أساسها ، متوافقة مع نفس الملف القابل للتنفيذ. يمكن بعد ذلك تضمين عمليات التحقق هذه (لـ golangci-lint) أو الملف القابل للتنفيذ (لـ gometalinter) في meta-linters المذكورة أعلاه.
افترض أن أحد الشيكات المتوافقة مع lintpack
هو جزء من golangci-lint
. إذا كانت هناك أي مشكلة تتعلق golangci-lint
للاستخدام ، فقد تكون هذه مسؤولية golangci-lint
، ولكن إذا كان من الخطأ تنفيذ التحقق نفسه ، فهذه هي مشكلة مؤلفي التحقق ، lintpack ، النظام البيئي.
وبعبارة أخرى ، تحل هذه المشاريع مشاكل مختلفة.
ماذا عن الناقد؟
lintpack
عملية نقل go-critic
إلى lintpack
؛ يمكن العثور على الداما في مستودع الناقد / الداما .
من غير المنطقي استخدام go-critic
خارج golangci-lint
، ولكن lintpack
يمكن أن يسمح لك بتثبيت تلك الشيكات غير المدرجة في go-critic
. على سبيل المثال ، قد تكون هذه التشخيصات التي كتبتها.
يتبع
سوف تتعلم كيفية إنشاء lintpack
المتوافقة مع lintpack
في المقالة التالية.
هناك سنقوم بتحليل المزايا التي تحصل عليها عند تنفيذ اللنتر القائم على lintpack مقارنة بالتنفيذ من البداية.
آمل أن يكون لديك شهية لإجراء فحوصات جديدة لـ Go. اسمحوا لي أن أعرف كم يصبح التحليل الثابت أكثر من اللازم ، وسنعمل على حل هذه المشكلة معًا بسرعة.