डार्ट में कोड जनरेशन। भाग 2. एनोटेशन, source_gen और build_runner

पहले भाग में, हमें पता चला कि डार्ट में कोड जनरेशन के लिए आवश्यक कोड क्यों आवश्यक हैं। दूसरे भाग में, हम सीखेंगे कि डार्ट में एनोटेशन कैसे बनाएं और उपयोग करें, साथ ही कोड पीढ़ी शुरू करने के लिए source_gen और build_runner का उपयोग कैसे करें।



डार्ट एनोटेशन


एनोटेशन सिंटैक्टिक मेटाडेटा है जिसे कोड में जोड़ा जा सकता है। दूसरे शब्दों में, यह कोड के किसी भी घटक के लिए अतिरिक्त जानकारी जोड़ने का एक अवसर है, उदाहरण के लिए, एक वर्ग या विधि के लिए। डार्ट कोड में एनोटेशन का व्यापक रूप से उपयोग किया जाता है: हम यह @required लिए @required का उपयोग करते हैं कि नामित पैरामीटर की आवश्यकता है, और एनोटेट पैरामीटर निर्दिष्ट नहीं होने पर हमारा कोड संकलित नहीं होगा। हम यह @override लिए @override का उपयोग करते हैं कि पैरेंट क्लास में परिभाषित API चाइल्ड क्लास में लागू है। एनोटेशन हमेशा @ सिंबल से शुरू होता है।


अपनी खुद की एनोटेशन कैसे बनाएं?


यद्यपि कोड में मेटाडेटा जोड़ने का विचार थोड़ा विदेशी और जटिल लगता है, एनोटेशन डार्ट भाषा में सबसे सरल चीजों में से एक है। यह पहले कहा गया था कि एनोटेशन में अतिरिक्त जानकारी होती है । वे PODO (प्लेन ओल्ड डार्ट ऑब्जेक्ट्स) के समान हैं। और कोई भी वर्ग एक एनोटेशन के रूप में काम कर सकता है यदि उसमें एक कंस्ट्रक्टर को परिभाषित किया गया हो :


 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 एक डार्ट पैकेज है, जो हमें डार्ट कोड का उपयोग करके फाइल बनाने में मदद करेगा। हम build.yaml का उपयोग करके Builder फ़ाइलों को कॉन्फ़िगर करेंगे। जब इसे कॉन्फ़िगर किया जाता है, तो Builder को प्रत्येक build कमांड पर या फ़ाइल बदलने पर बुलाया जाएगा। हमारे पास कोड को पार्स करने का भी अवसर है जिसे संशोधित किया गया है या कुछ मानदंडों को पूरा करता है।


source_gen डार्ट कोड को समझने के लिए


एक अर्थ में, build_runner एक तंत्र है जो प्रश्न का उत्तर देता है "मुझे कोड उत्पन्न करने की आवश्यकता कब है?" उसी समय, source_gen प्रश्न का उत्तर देता है "कोड क्या उत्पन्न किया जाना चाहिए?"। source_gen build_runner करने के लिए build_runner को काम करने के लिए एक ढांचा प्रदान करता है। इसके अलावा source_gen कोड को पार्स और जेनरेट करने के लिए एक सुविधाजनक एपीआई प्रदान करता है।


यह सब एक साथ रखना: TODO रिपोर्ट


इस लेख के शेष भाग में, हम todo_reporter.dart प्रोजेक्ट को अलग करेंगे, जो यहां पाया जा सकता है


एक अलिखित नियम है कि कोड पीढ़ी का उपयोग करने वाली सभी परियोजनाएं अनुसरण करती हैं: आपको एनोटेशन वाले पैकेज बनाने की आवश्यकता होती है, और जनरेटर के लिए एक अलग पैकेज जो इन एनोटेशन का उपयोग करता है। डार्ट / स्पंदन में एक पैकेज लाइब्रेरी बनाने के बारे में जानकारी यहाँ पाई जा सकती है


सबसे पहले आपको todo_reporter.dart निर्देशिका बनाने की आवश्यकता है। इस निर्देशिका के अंदर आपको todo_reporter निर्देशिका बनाने की आवश्यकता होती है, जिसमें एनोटेशन को संसाधित करने के लिए एनोटेशन, todo_reporter_generator निर्देशिका शामिल होगी, और अंत में, example निर्देशिका जिसमें लाइब्रेरी की क्षमताओं का प्रदर्शन हो रहा है।


प्रत्यय .dart स्पष्टता के लिए रूट निर्देशिका नाम में जोड़ा गया है। बेशक, यह आवश्यक नहीं है, लेकिन मैं इस नियम का पालन करना पसंद करता हूं ताकि इस तथ्य को सटीक रूप से इंगित किया जा सके कि इस पैकेज का उपयोग किसी भी डार्ट परियोजना में किया जा सकता है। इसके विपरीत, अगर मैं यह इंगित करना चाहता था कि यह पैकेज केवल फ़्लटर (जैसे ओज़ी.फ्लैटर ) के लिए है, तो मैं एक अलग प्रत्यय का उपयोग करूंगा। यह आवश्यक नहीं है, यह सिर्फ एक नामकरण सम्मेलन है जिसका मैं पालन करने की कोशिश करता हूं।


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 पैकेज को छोड़कर कोई निर्भरता नहीं है।


कार्य निर्देशिका में, निम्न कार्य करें:


  • आपको todo_reporter.dart फ़ाइल बनाने की todo_reporter.dart है, जिसमें export का उपयोग करते हुए, सार्वजनिक एपीआई वाले सभी वर्गों को निर्दिष्ट किया जाएगा। यह अच्छा अभ्यास है, क्योंकि हमारे पैकेज में किसी भी वर्ग को import 'package:todo_reporter/todo_reporter.dart'; का उपयोग करके import 'package:todo_reporter/todo_reporter.dart'; किया जा सकता है import 'package:todo_reporter/todo_reporter.dart'; । आप इस वर्ग को यहाँ देख सकते हैं।
  • हम सभी डायरेक्टरी - पब्लिक और नॉन-पब्लिक वाले src डायरेक्टरी बनाएंगे।

हमारे मामले में, हमें केवल एक एनोटेशन जोड़ना होगा। चलो हमारे एनोटेशन के साथ एक 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 पैकेज बनाते हैं। इस पैकेज के अंदर pubspec.yaml और build.yaml और एक build.yaml निर्देशिका होनी चाहिए। lib निर्देशिका में src निर्देशिका और builder.dart फ़ाइल होनी चाहिए। हमारे 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_factories है जिसमें Builder होता है, और builder_factories माल कोड उत्पन्न करने वाले तरीकों को इंगित करता है।


अब हम lib निर्देशिका में builder.dart फ़ाइल बना सकते हैं:


 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'); 

और src निर्देशिका में todo_reporter_generator.dart फ़ाइल:


 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 फ़ाइल में हमने Builder को बनाने वाले todoReporter विधि को परिभाषित किया है। Builder को SharedPartBuilder का उपयोग करके बनाया गया है, जो हमारे TodoReporterGenerator का उपयोग करता है। तो build_runner और source_gen मिलकर काम करते हैं।


हमारा TodoReporterGenerator GeneratorForAnnotation TodoReporterGenerator का एक उपवर्ग है, इसलिए generateForAnnotatedElement TodoReporterGenerator पद्धति केवल तभी निष्पादित की जाएगी जब यह एनोटेशन (हमारे मामले में @Todo ) कोड में पाया जाता है।


generateForAnnotatedElement मेथड एक स्ट्रिंग देता है जिसमें हमारा उत्पन्न कोड होता है। यदि उत्पन्न कोड संकलित नहीं करता है, तो संपूर्ण बिल्ड चरण विफल हो जाएगा । यह बहुत उपयोगी है क्योंकि यह भविष्य में त्रुटियों से बचा जाता है।


इस प्रकार, प्रत्येक कोड जनरेशन के साथ, हमारा 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! 

हमने जो चाहा वो हासिल किया! अब हम अपने कोड में प्रत्येक @Todo एनोटेशन के लिए सही डार्ट फ़ाइल उत्पन्न कर सकते हैं। जितना हो सके उतना प्रयास करें और बनाएं।


अगले लेख में


अब हमारे पास फाइल बनाने के लिए सही सेटिंग्स हैं। अगले लेख में, हम सीखेंगे कि एनोटेशन का उपयोग कैसे करें ताकि उत्पन्न कोड वास्तव में अच्छी चीजें कर सकें। आखिरकार, अब जो कोड जनरेट किया जा रहा है, उसका कोई मतलब नहीं है।

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


All Articles