كود الجيل في دارت. الجزء 2. الشروح ، source_gen و build_runner

في الجزء الأول ، اكتشفنا سبب الحاجة إلى إنشاء الشفرة وسردنا الأدوات اللازمة لإنشاء الشفرة في Dart. في الجزء الثاني ، سنتعلم كيفية إنشاء التعليقات التوضيحية واستخدامها في Dart ، وكذلك كيفية استخدام source_gen و build_runner لبدء إنشاء الكود.



دارت الشروح


التعليقات التوضيحية هي بيانات وصفية نحوية يمكن إضافتها إلى الكود. بمعنى آخر ، إنها فرصة لإضافة معلومات إضافية إلى أي مكون من عناصر التعليمات البرمجية ، على سبيل المثال ، إلى فئة أو طريقة. تُستخدم التعليقات التوضيحية على نطاق واسع في رمز Dart: نستخدم @required للإشارة إلى أن المعلمة المسماة مطلوبة ، ولن يتم تجميع الكود الخاص بنا إذا لم يتم تحديد المعلمة المشروحة. نستخدم أيضًا @override للإشارة إلى أنه يتم تنفيذ واجهة برمجة تطبيقات (API) محددة في فئة رئيسية في فصل تابع. تبدأ التعليقات التوضيحية دائمًا بالرمز @ .


كيفية إنشاء الشرح الخاص بك؟


على الرغم من أن فكرة إضافة البيانات الوصفية إلى الكود تبدو غريبة ومعقدة بعض الشيء ، إلا أن التعليقات التوضيحية هي واحدة من أبسط الأشياء في لغة Dart. قيل سابقًا أن التعليقات التوضيحية تحمل ببساطة معلومات إضافية . وهي تشبه PODO (كائنات دارت عادي قديم). وأي صف يمكن أن يكون بمثابة تعليق توضيحي إذا تم تعريف مُنشئ const فيه :


 class { final String name; final String todoUrl; const Todo(this.name, {this.todoUrl}) : assert(name != null); } @Todo('hello first annotation', todoUrl: 'https://www.google.com') class HelloAnnotations {} 

كما ترون ، التعليقات التوضيحية بسيطة للغاية. وما يهم هو ما سنفعله مع هذه الشروح. هذا سوف يساعدنا source_gen و build_runner .


كيفية استخدام build_runner؟


build_runner هي حزمة Dart التي ستساعدنا على إنشاء ملفات باستخدام كود Dart. سنقوم بتكوين ملفات Builder باستخدام build.yaml . عندما يتم تكوينه ، سيتم استدعاء Builder في كل أمر build أو عندما يتم تغيير الملف. لدينا أيضًا فرصة لتحليل الكود الذي تم تعديله أو استيفائه لمعايير معينة.


source_gen لفهم رمز دارت


بمعنى ما ، build_runner هي آلية تجيب على السؤال " متى أحتاج إلى إنشاء رمز؟" في الوقت نفسه ، يجيب source_gen عن السؤال " ما هي الشفرة التي ينبغي إنشاؤها؟". يوفر source_gen إطار عمل لإنشاء Builders for build_runner للعمل. كما يوفر source_gen واجهة برمجة تطبيقات ملائمة لتحليل وإنشاء التعليمات البرمجية.


وضع كل ذلك معا: تقرير TODO


في الجزء المتبقي من هذه المقالة ، سنفصل مشروع todo_reporter.dart ، والذي يمكن العثور عليه هنا .


هناك قاعدة غير مكتوبة تتبعها جميع المشروعات التي تستخدم إنشاء التعليمات البرمجية: تحتاج إلى إنشاء حزمة تحتوي على تعليقات توضيحية ، وحزمة منفصلة للمولد الذي يستخدم هذه التعليقات التوضيحية. يمكن العثور على معلومات حول كيفية إنشاء مكتبة حزم في Dart / Flutter هنا .


تحتاج أولاً إلى إنشاء دليل todo_reporter.dart . داخل هذا الدليل ، تحتاج إلى إنشاء دليل todo_reporter ، والذي سيحتوي على التعليق التوضيحي ، todo_reporter_generator لمعالجة التعليق التوضيحي ، وأخيراً ، دليل example يحتوي على عرض توضيحي لقدرات المكتبة التي يتم إنشاؤها.


.dart إضافة لاحقة .dart إلى اسم الدليل الجذر للتوضيح. بالطبع ، هذا ليس ضروريًا ، لكني أرغب في اتباع هذه القاعدة للإشارة بدقة إلى حقيقة أن هذه الحزمة يمكن استخدامها في أي مشروع Dart. على العكس من ذلك ، إذا أردت الإشارة إلى أن هذه الحزمة مخصصة فقط لـ Flutter (مثل ozzie.flutter ) ، فسأستخدم لاحقة مختلفة. هذا ليس ضروريًا ، إنه مجرد اصطلاح تسمية أحاول الالتزام به.


إنشاء todo_reporter ، حزمة التعليقات التوضيحية البسيطة


سنقوم بإنشاء todo_reporter داخل todo_reporter.dart . للقيام بذلك ، قم بإنشاء ملف pubspec.yaml lib .


pubspec.yaml بسيط جدًا:


 name: todo_reporter description: Keep track of all your TODOs. version: 1.0.0 author: Jorge Coca <jcocaramos@gmail.com> homepage: https://github.com/jorgecoca/todo_reporter.dart environment: sdk: ">=2.0.0 <3.0.0" dependencies: dev_dependencies: test: 1.3.4 

لا توجد تبعيات باستثناء حزمة test المستخدمة في عملية التطوير.


في دليل lib ، قم بما يلي:


  • تحتاج إلى إنشاء ملف todo_reporter.dart ، حيث ، باستخدام export ، سيتم تحديد جميع الفئات التي لها واجهة برمجة تطبيقات عامة. هذه ممارسة جيدة ، حيث يمكن استيراد أي فئة في الحزمة الخاصة بنا باستخدام import 'package:todo_reporter/todo_reporter.dart'; . يمكنك أن ترى هذه الفئة هنا .
  • داخل دليل lib ، سنقوم بإنشاء دليل src يحتوي على جميع الشفرات - العامة وغير العامة.

في حالتنا ، كل ما نحتاج إلى إضافته هو تعليق توضيحي. لنقم بإنشاء ملف todo.dart مع todo.dart التوضيحي:


 class Todo { final String name; final String todoUrl; const Todo(this.name, {this.todoUrl}) : assert(name != null); } 

هذا كل ما يتطلبه الأمر للتعليق. قلت أنها ستكون بسيطة. لكن هذا ليس كل شيء. دعنا نضيف اختبارات الوحدة إلى دليل test :


todo_test.dart
 import 'package:test/test.dart'; import 'package:todo_reporter/todo_reporter.dart'; void main() { group('Todo annotation', () { test('must have a non-null name', () { expect(() => Todo(null), throwsA(TypeMatcher<AssertionError>())); }); test('does not need to have a todoUrl', () { final todo = Todo('name'); expect(todo.todoUrl, null); }); test('if it is a given a todoUrl, it will be part of the model', () { final givenUrl = 'http://url.com'; final todo = Todo('name', todoUrl: givenUrl); expect(todo.todoUrl, givenUrl); }); }); } 

هذا هو كل ما نحتاجه لإنشاء التعليق التوضيحي. يمكنك العثور على الكود هنا . الآن يمكننا أن نذهب إلى المولد.


القيام بعمل رائع: todo_reporter_generator


الآن وقد عرفنا كيفية إنشاء حزم ، فلنقم بإنشاء حزمة todo_reporter_generator . يجب أن تكون داخل هذه الحزمة build.yaml و build.yaml lib . يجب أن يكون دليل lib دليل src وملف builder.dart . يُعد todo_reporter_generator الخاص todo_reporter_generator حزمة منفصلة ستتم إضافتها باعتبارها dev_dependency لمشاريع أخرى. هذا لأن إنشاء الكود مطلوب فقط في مرحلة التطوير ، ولا يحتاج إلى إضافته إلى التطبيق النهائي.


pubspec.yaml كما يلي:


 name: todo_reporter_generator description: An annotation processor for @Todo annotations. version: 1.0.0 author: Jorge Coca <jcocaramos@gmail.com> homepage: https://github.com/jorgecoca/todo_reporter.dart environment: sdk: ">=2.0.0 <3.0.0" dependencies: build: '>=0.12.0 <2.0.0' source_gen: ^0.9.0 todo_reporter: path: ../todo_reporter/ dev_dependencies: build_test: ^0.10.0 build_runner: '>=0.9.0 <0.11.0' test: ^1.0.0 

الآن لنقم بإنشاء build.yaml . يحتوي هذا الملف على التكوين الضروري لبناةنا . مزيد من التفاصيل يمكن العثور عليها هنا . build.yaml النحو التالي:


 targets: $default: builders: todo_reporter_generator|todo_reporter: enabled: true builders: todo_reporter: target: ":todo_reporter_generator" import: "package:todo_reporter_generator/builder.dart" builder_factories: ["todoReporter"] build_extensions: {".dart": [".todo_reporter.g.part"]} auto_apply: dependents build_to: cache applies_builders: ["source_gen|combining_builder"] 

تشير خاصية import إلى الملف الذي يحتوي على Builder ، وتشير خاصية builder_factories إلى الأساليب التي ستنشئ الكود.


الآن يمكننا إنشاء ملف builder.dart في دليل lib :


 import 'package:build/build.dart'; import 'package:source_gen/source_gen.dart'; import 'package:todo_reporter_generator/src/todo_reporter_generator.dart'; Builder todoReporter(BuilderOptions options) => SharedPartBuilder([TodoReporterGenerator()], 'todo_reporter'); 

وملف todo_reporter_generator.dart في دليل src :


 import 'dart:async'; import 'package:analyzer/dart/element/element.dart'; import 'package:build/src/builder/build_step.dart'; import 'package:source_gen/source_gen.dart'; import 'package:todo_reporter/todo_reporter.dart'; class TodoReporterGenerator extends GeneratorForAnnotation<Todo> { @override FutureOr<String> generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep) { return "// Hey! Annotation found!"; } } 

كما ترون ، في ملف builder.dart قمنا بتعريف طريقة todoReporter التي ينشئها Builder . يتم إنشاء Builder باستخدام SharedPartBuilder ، والذي يستخدم TodoReporterGenerator . لذلك build_runner و source_gen العمل معا.


TodoReporterGenerator الخاص TodoReporterGenerator هو فئة فرعية من GeneratorForAnnotation ، لذلك لن يتم تنفيذ طريقة @Todo إلا عند العثور على هذا التعليق التوضيحي ( @Todo في حالتنا) في الكود.


تقوم generateForAnnotatedElement generForAnnotatedElement بإرجاع سلسلة تحتوي على الكود الذي تم إنشاؤه. إذا لم يتم تجميع التعليمات البرمجية المنشأة ، فسوف تفشل مرحلة الإنشاء بأكملها . هذا مفيد للغاية لأنه يتجنب الأخطاء في المستقبل.


وبالتالي ، مع كل جيل من الشفرات ، todo_repoter_generator ملف part ، مع تعليق // Hey! Annotation found! // Hey! Annotation found! في المقالة التالية ، سنتعلم كيفية معالجة التعليقات التوضيحية.


ضعها جميعًا معًا: باستخدام todo_reporter


يمكنك الآن شرح كيفية todo_reporter.dart . من الممارسات الجيدة إضافة مشروع example عند العمل مع الحزم. لذلك سيتمكن المطورون الآخرون من معرفة كيفية استخدام واجهة برمجة التطبيقات في مشروع حقيقي.


لنقم بإنشاء مشروع وإضافة التبعيات المطلوبة إلى pubspec.yaml . في حالتنا ، سننشئ مشروع رفرفة داخل دليل example ونضيف التبعيات:


 dependencies: flutter: sdk: flutter todo_reporter: path: ../todo_reporter/ dev_dependencies: build_runner: 1.0.0 flutter_test: sdk: flutter todo_reporter_generator: path: ../todo_reporter_generator/ 

بعد تلقي الحزم ( flutter packages get ) ، يمكننا استخدام التعليق التوضيحي الخاص بنا:


 import 'package:todo_reporter/todo_reporter.dart'; @Todo('Complete implementation of TestClass') class TestClass {} 

الآن بعد أن أصبح كل شيء في مكانه ، قم بتشغيل مولدنا:


 $ flutter packages pub run build_runner build 

بعد اكتمال الأمر ، ستلاحظ وجود ملف جديد في مشروعنا: todo.g.dart . وسوف تحتوي على ما يلي:


 // GENERATED CODE - DO NOT MODIFY BY HAND part of 'todo.dart'; // ***************************************************************** // TodoReporterGenerator // ******************************************************************** // Hey! Annotation found! 

لقد حققنا ما أردنا! الآن يمكننا إنشاء ملف Dart الصحيح لكل تعليق توضيحي على @Todo في التعليمات البرمجية الخاصة بنا. حاول وإنشاء ما تحتاج إليه.


في المقال التالي


الآن لدينا الإعدادات الصحيحة لإنشاء الملفات. في المقالة التالية ، سوف نتعلم كيفية استخدام التعليقات التوضيحية حتى تتمكن الشفرة التي تم إنشاؤها من فعل أشياء رائعة حقًا. بعد كل شيء ، الكود الذي يتم إنشاؤه الآن لا معنى له.

Source: https://habr.com/ru/post/ar446264/


All Articles