portaldacalheta.pt
  • Κύριος
  • Επιστήμη Δεδομένων Και Βάσεις Δεδομένων
  • Κατανεμημένες Ομάδες
  • Ευκίνητο Ταλέντο
  • Κερδοφορία & Αποδοτικότητα
Πίσω Μέρος

Γράψτε κώδικα για να ξαναγράψετε τον κωδικό σας: jscodeshift



Codemods με jscodeshift

Πόσες φορές έχετε χρησιμοποιήσει τη λειτουργία εύρεσης και αντικατάστασης σε έναν κατάλογο για να κάνετε αλλαγές στα αρχεία προέλευσης JavaScript; Εάν είστε καλοί, έχετε φανταστεί και χρησιμοποιείτε τυπικές εκφράσεις με ομάδες σύλληψης, γιατί αξίζει τον κόπο αν η βάση του κώδικα σας είναι αρκετά μεγάλη. Ωστόσο, το Regex έχει όρια. Για μη ασήμαντες αλλαγές, χρειάζεστε έναν προγραμματιστή που κατανοεί τον κώδικα στο πλαίσιο και είναι επίσης πρόθυμος να αναλάβει τη μακρά, κουραστική και επιρρεπή σε σφάλματα διαδικασία.

Εδώ μπαίνουν τα 'codemods'.



Τα Codemods είναι σενάρια που χρησιμοποιούνται για την επανεγγραφή άλλων σεναρίων. Σκεφτείτε τα ως λειτουργίες εύρεσης και αντικατάστασης που μπορούν να διαβάζουν και να γράφουν κώδικα. Μπορείτε να τους χρησιμοποιήσετε για να ενημερώσετε τον πηγαίο κώδικα για να ταιριάζει στις συμβάσεις κωδικοποίησης μιας ομάδας, να κάνετε ευρείες αλλαγές όταν τροποποιείται ένα API ή ακόμα και να διορθώσετε αυτόματα τον υπάρχοντα κώδικα όταν το δημόσιο πακέτο σας κάνει μια αλλαγή.



Η εργαλειοθήκη jscodeshift είναι ιδανική για εργασία με κωδικούς κωδικούς.



Σκεφτείτε τα codemods ως εύρεση σεναρίου και αντικαταστήστε τη λειτουργικότητα που μπορεί να διαβάσει και να γράψει κώδικα. Τιτίβισμα

Σε αυτό το άρθρο, θα εξερευνήσουμε ένα κιτ εργαλείων για κωδικούς κωδικούς που ονομάζονται 'jscodeshift', δημιουργώντας ταυτόχρονα τρία κωδικοκώδικα με αυξανόμενη πολυπλοκότητα. Μέχρι το τέλος θα έχετε ευρεία έκθεση στις σημαντικές πτυχές του jscodeshift και θα είστε έτοιμοι να ξεκινήσετε τη σύνταξη των δικών σας κωδικών κωδικών. Θα περάσουμε από τρεις ασκήσεις που καλύπτουν κάποιες βασικές, αλλά φοβερές, χρήσεις κωδικών κωδικών και μπορείτε να δείτε τον πηγαίο κώδικα για αυτές τις ασκήσεις στο my έργο github .

Τι είναι το jscodeshift;

Η εργαλειοθήκη jscodeshift σάς επιτρέπει να αντλείτε μια δέσμη αρχείων προέλευσης μέσω ενός μετασχηματισμού και να τα αντικαθιστάτε με αυτό που βγαίνει από το άλλο άκρο. Μέσα στον μετασχηματισμό, αναλύετε την πηγή σε ένα αφηρημένο δέντρο σύνταξης (AST), σπρώξτε γύρω για να κάνετε τις αλλαγές σας και, στη συνέχεια, αναδημιουργήστε την πηγή από το αλλοιωμένο AST.



Η διεπαφή που παρέχει το jscodeshift είναι ένα περιτύλιγμα γύρω στο recast και ast-types πακέτα. recast χειρίζεται τη μετατροπή από πηγή σε AST και πίσω ενώ ast-types χειρίζεται την αλληλεπίδραση χαμηλού επιπέδου με τους κόμβους AST.

Ρύθμιση

Για να ξεκινήσετε, εγκαταστήστε το jscodeshift παγκοσμίως από το npm.



npm i -g jscodeshift

Υπάρχουν επιλογές δρομέων που μπορείτε να χρησιμοποιήσετε και μια ρύθμιση δοκιμών με γνώμονα το οποίο καθιστά την εκτέλεση μιας σειράς δοκιμών μέσω Jest (ένα πλαίσιο δοκιμών ανοιχτού κώδικα JavaScript) πολύ εύκολη, αλλά θα το παρακάμψουμε προς το παρόν υπέρ της απλότητας:

jscodeshift -t some-transform.js input-file.js -d -p



Αυτό θα εκτελεστεί input-file.js μέσω του μετασχηματισμού some-transform.js και εκτυπώστε τα αποτελέσματα χωρίς να αλλάξετε το αρχείο.

πώς να φτιάξετε ένα παιχνίδι σε επεξεργασία

Πριν ξεκινήσετε, ωστόσο, είναι σημαντικό να κατανοήσετε τρεις βασικούς τύπους αντικειμένων με τους οποίους ασχολείται το API jscodeshift: κόμβους, διαδρομές κόμβων και συλλογές.



Κόμβοι

Οι κόμβοι είναι τα βασικά δομικά στοιχεία του AST, που συχνά αναφέρονται ως «κόμβοι AST». Αυτά είναι αυτά που βλέπετε κατά την εξερεύνηση του κωδικού σας με τον AST Explorer. Είναι απλά αντικείμενα και δεν παρέχουν μεθόδους.

Κόμβοι-διαδρομές

Οι διαδρομές κόμβων είναι περιτυλίγματα γύρω από έναν κόμβο AST που παρέχεται από ast-types ως τρόπος διέλευσης της αφηρημένης σύνταξης δέντρων (AST, θυμηθείτε;). Μεμονωμένα, οι κόμβοι δεν έχουν καμία πληροφορία σχετικά με τον γονέα ή το εύρος τους, επομένως οι κόμβοι-κόμβοι το φροντίζουν. Μπορείτε να αποκτήσετε πρόσβαση στον τυλιγμένο κόμβο μέσω του node ιδιότητα και υπάρχουν πολλές διαθέσιμες μέθοδοι για την αλλαγή του υποκείμενου κόμβου. Οι κόμβοι-κόμβοι αναφέρονται συχνά ως «μονοπάτια».



Συλλογές

Οι συλλογές είναι ομάδες μηδενικών ή περισσότερων διαδρομών κόμβου που επιστρέφει το API jscodeshift όταν υποβάλλετε ερώτημα στο AST. Έχουν κάθε είδους χρήσιμες μεθόδους, μερικές από τις οποίες θα διερευνήσουμε.

Οι συλλογές περιέχουν κόμβους κόμβων, κόμβοι κόμβων περιέχουν κόμβους και κόμβοι είναι από τους οποίους αποτελείται το AST. Λάβετε υπόψη αυτό και θα είναι εύκολο να κατανοήσετε το API ερωτημάτων jscodeshift.

Μπορεί να είναι δύσκολο να παρακολουθείτε τις διαφορές μεταξύ αυτών των αντικειμένων και των αντίστοιχων δυνατοτήτων API τους, επομένως υπάρχει ένα καλό εργαλείο που ονομάζεται jscodeshift-βοηθός που καταγράφει τον τύπο αντικειμένου και παρέχει άλλες βασικές πληροφορίες.

Η γνώση της διαφοράς μεταξύ κόμβων, διαδρομών κόμβων και συλλογών είναι σημαντική.

Η γνώση της διαφοράς μεταξύ κόμβων, διαδρομών κόμβων και συλλογών είναι σημαντική.

Άσκηση 1: Κατάργηση κλήσεων στην Κονσόλα

Για να βραχεί τα πόδια μας, ας ξεκινήσουμε με την κατάργηση κλήσεων σε όλες τις μεθόδους κονσόλας στη βάση κώδικα. Ενώ μπορείτε να το κάνετε αυτό με εύρεση και αντικατάσταση και λίγο regex, αρχίζει να γίνεται δύσκολο με δηλώσεις πολλαπλών γραμμών, γραμματοσειρές προτύπων και πιο περίπλοκες κλήσεις, οπότε είναι ένα ιδανικό παράδειγμα για να ξεκινήσετε.

Αρχικά, δημιουργήστε δύο αρχεία, remove-consoles.js και remove-consoles.input.js:

//remove-consoles.js export default (fileInfo, api) => { }; //remove-consoles.input.js export const sum = (a, b) => { console.log('calling sum with', arguments); return a + b; }; export const multiply = (a, b) => { console.warn('calling multiply with', arguments); return a * b; }; export const divide = (a, b) => { console.error(`calling divide with ${ arguments }`); return a / b; }; export const average = (a, b) => { console.log('calling average with ' + arguments); return divide(sum(a, b), 2); };

Εδώ είναι η εντολή που θα χρησιμοποιούμε στο τερματικό για να το προωθήσουμε μέσω του jscodeshift:

jscodeshift -t remove-consoles.js remove-consoles.input.js -d -p

Εάν όλα έχουν ρυθμιστεί σωστά, όταν το εκτελείτε θα πρέπει να δείτε κάτι τέτοιο.

Processing 1 files... Spawning 1 workers... Running in dry mode, no files will be written! Sending 1 files to free worker... All done. Results: 0 errors 0 unmodified 1 skipped 0 ok Time elapsed: 0.514seconds

Εντάξει, αυτό ήταν λίγο αντικλιματικό, καθώς ο μετασχηματισμός μας δεν κάνει τίποτα ακόμη, αλλά τουλάχιστον γνωρίζουμε ότι όλα λειτουργούν. Εάν δεν λειτουργεί καθόλου, βεβαιωθείτε ότι έχετε εγκαταστήσει το jscodeshift παγκοσμίως. Εάν η εντολή για την εκτέλεση του μετασχηματισμού είναι λανθασμένη, θα δείτε είτε ένα μήνυμα 'ERROR Transform file ... δεν υπάρχει' ή 'TypeError: path πρέπει να είναι μια συμβολοσειρά ή Buffer' εάν το αρχείο εισαγωγής δεν μπορεί να βρεθεί. Εάν έχετε κάτι με λίγα λόγια, θα πρέπει να εντοπίσετε εύκολα τα πολύ περιγραφικά σφάλματα μετασχηματισμού.

Σχετίζεται με: Γρήγορο και πρακτικό φύλλο εξαπάτησης JavaScript του ApeeScape: ES6 και πέρα

Ο τελικός μας στόχος όμως, μετά από μια επιτυχημένη μετατροπή, είναι να δούμε αυτήν την πηγή:

export const sum = (a, b) => { return a + b; }; export const multiply = (a, b) => { return a * b; }; export const divide = (a, b) => { return a / b; }; export const average = (a, b) => { return divide(sum(a, b), 2); };

Για να φτάσουμε εκεί, πρέπει να μετατρέψουμε την πηγή σε AST, να βρούμε τις κονσόλες, να τις αφαιρέσουμε και, στη συνέχεια, να μετατρέψουμε το τροποποιημένο AST σε πηγή. Τα πρώτα και τελευταία βήματα είναι εύκολα, είναι απλώς:

remove-consoles.js export default (fileInfo, api) => { const j = api.jscodeshift; const root = j(fileInfo.source); return root.toSource(); };

Αλλά πώς βρίσκουμε τις κονσόλες και τις αφαιρούμε; Εάν δεν έχετε εξαιρετικές γνώσεις σχετικά με το Mozilla Parser API, πιθανότατα θα χρειαστείτε ένα εργαλείο για να κατανοήσετε πώς φαίνεται το AST. Για αυτό μπορείτε να χρησιμοποιήσετε το Εξερεύνηση AST . Επικολλήστε τα περιεχόμενα του remove-consoles.input.js σε αυτό και θα δείτε το AST. Υπάρχουν πολλά δεδομένα ακόμη και στον απλούστερο κώδικα, επομένως βοηθά στην απόκρυψη δεδομένων και μεθόδων τοποθεσίας. Μπορείτε να αλλάξετε την ορατότητα των ιδιοτήτων στην Εξερεύνηση AST με τα πλαίσια ελέγχου πάνω από το δέντρο.

Μπορούμε να δούμε ότι οι μέθοδοι κλήσεων στην κονσόλα αναφέρονται ως CallExpressions, οπότε πώς τις βρίσκουμε στο μετασχηματισμό μας; Χρησιμοποιούμε τα ερωτήματα του jscodeshift, θυμόμαστε την προηγούμενη συζήτησή μας σχετικά με τις διαφορές μεταξύ των Συλλογών, των κόμβων και των ίδιων των κόμβων:

//remove-consoles.js export default (fileInfo, api) => { const j = api.jscodeshift; const root = j(fileInfo.source); return root.toSource(); };

Η γραμμή const root = j(fileInfo.source); επιστρέφει μια συλλογή μιας διαδρομής κόμβου, η οποία τυλίγει τον κόμβο AST ρίζας. Μπορούμε να χρησιμοποιήσουμε τη συλλογή find μέθοδος για αναζήτηση κόμβων απογόνου ενός συγκεκριμένου τύπου, όπως:

const callExpressions = root.find(j.CallExpression);

Αυτό επιστρέφει μια άλλη συλλογή διαδρομών κόμβων που περιέχουν μόνο τους κόμβους που είναι CallExpressions. Στην πρώτη κοκκινίλα, αυτό μοιάζει με αυτό που θέλουμε, αλλά είναι πολύ ευρύ. Ενδέχεται να καταλήξουμε να εκτελούμε εκατοντάδες ή χιλιάδες αρχεία μέσω των μετασχηματισμών μας, οπότε πρέπει να είμαστε ακριβείς για να έχουμε οποιαδήποτε εμπιστοσύνη ότι θα λειτουργήσει όπως είχε προβλεφθεί. Το αφελές find παραπάνω δεν θα βρει απλώς την κονσόλα CallExpressions, αλλά θα βρει κάθε CallExpression στην πηγή, συμπεριλαμβανομένης της

require('foo') bar() setTimeout(() => {}, 0)

Για να επιβάλουμε μεγαλύτερη ειδικότητα, παρέχουμε ένα δεύτερο όρισμα στο .find: Ένα αντικείμενο πρόσθετων παραμέτρων, κάθε κόμβος πρέπει να συμπεριληφθεί στα αποτελέσματα. Μπορούμε να κοιτάξουμε στον Εξερευνητή AST για να δούμε ότι η κονσόλα μας. * Οι κλήσεις έχουν τη μορφή:

{ 'type': 'CallExpression', 'callee': { 'type': 'MemberExpression', 'object': { 'type': 'Identifier', 'name': 'console' } } }

Με αυτές τις γνώσεις, ξέρουμε να τελειοποιούμε το ερώτημά μας με έναν προσδιοριστή που θα επιστρέφει μόνο τον τύπο CallExpressions που μας ενδιαφέρει:

const callExpressions = root.find(j.CallExpression, { callee: { type: 'MemberExpression', object: { type: 'Identifier', name: 'console' }, }, });

Τώρα που έχουμε μια ακριβή συλλογή των ιστότοπων κλήσεων, ας τους καταργήσουμε από το AST. Βολικά, ο τύπος αντικειμένου συλλογής έχει remove μέθοδος που θα κάνει ακριβώς αυτό. Το remove-consoles.js το αρχείο θα μοιάζει τώρα με αυτό:

//remove-consoles.js export default (fileInfo, api) => { const j = api.jscodeshift; const root = j(fileInfo.source) const callExpressions = root.find(j.CallExpression, { callee: { type: 'MemberExpression', object: { type: 'Identifier', name: 'console' }, }, } ); callExpressions.remove(); return root.toSource(); };

Τώρα, εάν εκτελέσουμε τον μετασχηματισμό μας από τη γραμμή εντολών χρησιμοποιώντας το jscodeshift -t remove-consoles.js remove-consoles.input.js -d -p, θα πρέπει να δούμε:

Processing 1 files... Spawning 1 workers... Running in dry mode, no files will be written! Sending 1 files to free worker... export const sum = (a, b) => { return a + b; }; export const multiply = (a, b) => { return a * b; }; export const divide = (a, b) => { return a / b; }; export const average = (a, b) => { return divide(sum(a, b), 2); }; All done. Results: 0 errors 0 unmodified 0 skipped 1 ok Time elapsed: 0.604seconds

Φαίνεται καλό. Τώρα που ο μετασχηματισμός μας αλλάζει το υποκείμενο AST, χρησιμοποιώντας το .toSource() δημιουργεί μια διαφορετική συμβολοσειρά από το πρωτότυπο. Η επιλογή -p από την εντολή μας εμφανίζει το αποτέλεσμα και στο κάτω μέρος εμφανίζεται ένας αριθμός καταθέσεων για κάθε αρχείο που υποβλήθηκε σε επεξεργασία. Η κατάργηση της επιλογής -d από την εντολή μας, θα αντικαταστήσει το περιεχόμενο του remove-consoles.input.js με την έξοδο από τον μετασχηματισμό.

Η πρώτη μας άσκηση ολοκληρώθηκε… σχεδόν. Ο κώδικας είναι παράξενος και πιθανώς πολύ προσβλητικός σε οποιονδήποτε λειτουργικό καθαριστή εκεί έξω, και έτσι για να κάνει τη ροή κώδικα μετασχηματισμού καλύτερη, το jscodeshift έκανε τα περισσότερα πράγματα αλυσοδεμένα. Αυτό μας επιτρέπει να ξαναγράψουμε τον μετασχηματισμό μας έτσι:

// remove-consoles.js export default (fileInfo, api) => { const j = api.jscodeshift; return j(fileInfo.source) .find(j.CallExpression, { callee: { type: 'MemberExpression', object: { type: 'Identifier', name: 'console' }, }, } ) .remove() .toSource(); };

Πολύ καλύτερα. Για να ανακεφαλαιώσετε την άσκηση 1, τυλίξαμε την πηγή, ζητήσαμε μια συλλογή από κόμβους-κόμβους, αλλάξαμε το AST και, στη συνέχεια, αναδημιουργήσαμε αυτήν την πηγή. Βρέξαμε τα πόδια μας με ένα πολύ απλό παράδειγμα και αγγίξαμε τις πιο σημαντικές πτυχές. Τώρα, ας κάνουμε κάτι πιο ενδιαφέρον.

Άσκηση 2: Αντικατάσταση εισερχόμενων κλήσεων μεθόδου

Για αυτό το σενάριο, έχουμε μια ενότητα 'γεωμετρίας' με μια μέθοδο που ονομάζεται 'circleArea' την οποία καταργήσαμε υπέρ του 'getCircleArea'. Θα μπορούσαμε εύκολα να τα βρούμε και να τα αντικαταστήσουμε με /geometry.circleArea/g, αλλά τι γίνεται αν ο χρήστης έχει εισαγάγει τη λειτουργική μονάδα και της έχει εκχωρήσει διαφορετικό όνομα; Για παράδειγμα:

import g from 'geometry'; const area = g.circleArea(radius);

Πώς θα γνωρίζαμε να αντικαταστήσουμε το g.circleArea αντί για geometry.circleArea; Σίγουρα δεν μπορούμε να υποθέσουμε ότι όλα circleArea οι κλήσεις είναι αυτές που αναζητούμε, χρειαζόμαστε κάποιο πλαίσιο. Εδώ ξεκινούν τα codemods την αξία τους. Ας ξεκινήσουμε κάνοντας δύο αρχεία, deprecated.js και deprecated.input.js.

//deprecated.js export default (fileInfo, api) => { const j = api.jscodeshift; const root = j(fileInfo.source); return root.toSource(); }; deprecated.input.js import g from 'geometry'; import otherModule from 'otherModule'; const radius = 20; const area = g.circleArea(radius); console.log(area === Math.pow(g.getPi(), 2) * radius); console.log(area === otherModule.circleArea(radius));

Τώρα εκτελέστε αυτήν την εντολή για να εκτελέσετε τον κωδικό κώδικα.

jscodeshift -t ./deprecated.js ./deprecated.input.js -d -p

Θα πρέπει να δείτε την έξοδο που δείχνει ότι ο μετασχηματισμός εκτελέστηκε, αλλά δεν έχει αλλάξει τίποτα ακόμη.

Processing 1 files... Spawning 1 workers... Running in dry mode, no files will be written! Sending 1 files to free worker... All done. Results: 0 errors 1 unmodified 0 skipped 0 ok Time elapsed: 0.892seconds

Πρέπει να γνωρίζουμε τι geometry η μονάδα έχει εισαχθεί ως. Ας δούμε την Εξερεύνηση AST και να καταλάβουμε τι ψάχνουμε. Η εισαγωγή μας λαμβάνει αυτήν τη μορφή.

{ 'type': 'ImportDeclaration', 'specifiers': [ { 'type': 'ImportDefaultSpecifier', 'local': { 'type': 'Identifier', 'name': 'g' } } ], 'source': { 'type': 'Literal', 'value': 'geometry' } }

Μπορούμε να καθορίσουμε έναν τύπο αντικειμένου για να βρούμε μια συλλογή κόμβων όπως αυτή:

const importDeclaration = root.find(j.ImportDeclaration, { source: { type: 'Literal', value: 'geometry', }, });

Αυτό μας δίνει το ImportDeclaration που χρησιμοποιείται για την εισαγωγή «γεωμετρίας». Από εκεί, σκάψτε για να βρείτε το τοπικό όνομα που χρησιμοποιείται για τη συγκράτηση της εισαγόμενης λειτουργικής μονάδας. Δεδομένου ότι είναι η πρώτη φορά που το κάναμε, ας επισημάνουμε ένα σημαντικό και μπερδεμένο σημείο κατά την πρώτη εκκίνηση.

Σημείωση: Είναι σημαντικό να γνωρίζετε ότι root.find() επιστρέφει μια συλλογή κόμβων-διαδρομών. Από εκεί, το .get(n) Η μέθοδος επιστρέφει τη διαδρομή κόμβου στο ευρετήριο n σε αυτήν τη συλλογή, και για να πάρουμε τον πραγματικό κόμβο, χρησιμοποιούμε .node. Ο κόμβος είναι βασικά αυτό που βλέπουμε στον AST Explorer. Θυμηθείτε, η διαδρομή κόμβου είναι κυρίως πληροφορίες σχετικά με το εύρος και τις σχέσεις του κόμβου, όχι ο ίδιος ο κόμβος.

// find the Identifiers const identifierCollection = importDeclaration.find(j.Identifier); // get the first NodePath from the Collection const nodePath = identifierCollection.get(0); // get the Node in the NodePath and grab its 'name' const localName = nodePath.node.name;

Αυτό μας επιτρέπει να καταλάβουμε δυναμικά τι geometry η μονάδα έχει εισαχθεί ως. Στη συνέχεια, βρίσκουμε τα μέρη που χρησιμοποιείται και τα αλλάζουμε. Κοιτάζοντας τον AST Explorer, μπορούμε να δούμε ότι πρέπει να βρούμε εκφράσεις μελών που μοιάζουν με αυτό:

{ 'type': 'MemberExpression', 'object': { 'name': 'geometry' }, 'property': { 'name': 'circleArea' } }

Θυμηθείτε, ωστόσο, ότι η ενότητα μας μπορεί να έχει εισαχθεί με διαφορετικό όνομα, οπότε πρέπει να το λάβουμε υπόψη, κάνοντας το ερώτημά μας να μοιάζει με αυτό:

j.MemberExpression, { object: { name: localName, }, property: { name: 'circleArea', }, })

Τώρα που έχουμε ένα ερώτημα, μπορούμε να πάρουμε μια συλλογή όλων των ιστότοπων κλήσεων στην παλιά μας μέθοδο και στη συνέχεια να χρησιμοποιήσουμε τη συλλογή replaceWith() μέθοδο για την ανταλλαγή τους. Το replaceWith() Η μέθοδος επαναλαμβάνεται μέσω της συλλογής, περνώντας κάθε διαδρομή κόμβου σε μια συνάρτηση επανάκλησης. Στη συνέχεια, ο κόμβος AST αντικαθίσταται με οποιονδήποτε κόμβο επιστρέφετε από την επιστροφή κλήσης.

Τα Codemods σας επιτρέπουν να δημιουργήσετε σενάριο

Και πάλι, η κατανόηση της διαφοράς μεταξύ συλλογών, διαδρομών κόμβων και κόμβων είναι απαραίτητη για να έχει νόημα.

Μόλις τελειώσουμε με την αντικατάσταση, δημιουργούμε την πηγή ως συνήθως. Εδώ είναι ο τελικός μετασχηματισμός μας:

//deprecated.js export default (fileInfo, api) => { const j = api.jscodeshift; const root = j(fileInfo.source); // find declaration for 'geometry' import const importDeclaration = root.find(j.ImportDeclaration, { source: { type: 'Literal', value: 'geometry', }, }); // get the local name for the imported module const localName = // find the Identifiers importDeclaration.find(j.Identifier) // get the first NodePath from the Collection .get(0) // get the Node in the NodePath and grab its 'name' .node.name; return root.find(j.MemberExpression, { object: { name: localName, }, property: { name: 'circleArea', }, }) .replaceWith(nodePath => { // get the underlying Node const { node } = nodePath; // change to our new prop node.property.name = 'getCircleArea'; // replaceWith should return a Node, not a NodePath return node; }) .toSource(); };

Όταν εκτελούμε την πηγή μέσω του μετασχηματισμού, βλέπουμε ότι η κλήση προς τη μέθοδο που έχει καταργηθεί στο geometry η ενότητα άλλαξε, αλλά τα υπόλοιπα αφέθηκαν αμετάβλητα, έτσι:

import g from 'geometry'; import otherModule from 'otherModule'; const radius = 20; const area = g.getCircleArea(radius); console.log(area === Math.pow(g.getPi(), 2) * radius); console.log(area === otherModule.circleArea(radius));

Άσκηση 3: Αλλαγή υπογραφής μεθόδου

Στις προηγούμενες ασκήσεις καλύψαμε συλλογές ερωτήσεων για συγκεκριμένους τύπους κόμβων, την αφαίρεση κόμβων και την αλλαγή κόμβων, αλλά τι γίνεται με τη δημιουργία εντελώς νέων κόμβων; Αυτό θα αντιμετωπίσουμε σε αυτήν την άσκηση.

Σε αυτό το σενάριο, έχουμε μια υπογραφή μεθόδου που ξεφεύγει από τον έλεγχο με μεμονωμένα ορίσματα καθώς το λογισμικό έχει αναπτυχθεί, και έτσι αποφασίστηκε ότι θα ήταν καλύτερα να αποδεχτούμε ένα αντικείμενο που περιέχει αυτά τα επιχειρήματα.

Αντί για car.factory('white', 'Kia', 'Sorento', 2010, 50000, null, true);

θα θέλαμε να δούμε

const suv = car.factory({ color: 'white', make: 'Kia', model: 'Sorento', year: 2010, miles: 50000, bedliner: null, alarm: true, });

Ας ξεκινήσουμε κάνοντας τον μετασχηματισμό και ένα αρχείο εισαγωγής για δοκιμή με:

//signature-change.js export default (fileInfo, api) => { const j = api.jscodeshift; const root = j(fileInfo.source); return root.toSource(); }; //signature-change.input.js import car from 'car'; const suv = car.factory('white', 'Kia', 'Sorento', 2010, 50000, null, true); const truck = car.factory('silver', 'Toyota', 'Tacoma', 2006, 100000, true, true);

Η εντολή μας για εκτέλεση του μετασχηματισμού θα είναι jscodeshift -t signature-change.js signature-change.input.js -d -p και τα βήματα που πρέπει να πραγματοποιήσουμε αυτόν τον μετασχηματισμό είναι:

  • Βρείτε το τοπικό όνομα για την εισαγόμενη λειτουργική μονάδα
  • Βρείτε όλους τους ιστότοπους κλήσεων στη μέθοδο .factory
  • Διαβάστε όλα τα επιχειρήματα που διαβιβάζονται
  • Αντικαταστήστε αυτήν την κλήση με ένα μόνο όρισμα που περιέχει ένα αντικείμενο με τις αρχικές τιμές

Χρησιμοποιώντας τον AST Explorer και τη διαδικασία που χρησιμοποιήσαμε στις προηγούμενες ασκήσεις, τα πρώτα δύο βήματα είναι εύκολα:

//signature-change.js export default (fileInfo, api) => { const j = api.jscodeshift; const root = j(fileInfo.source); // find declaration for 'car' import const importDeclaration = root.find(j.ImportDeclaration, { source: { type: 'Literal', value: 'car', }, }); // get the local name for the imported module const localName = importDeclaration.find(j.Identifier) .get(0) .node.name; // find where `.factory` is being called return root.find(j.CallExpression, { callee: { type: 'MemberExpression', object: { name: localName, }, property: { name: 'factory', }, } }) .toSource(); };

Για να διαβάσετε όλα τα επιχειρήματα που διαβιβάζονται αυτήν τη στιγμή, χρησιμοποιούμε το replaceWith() μέθοδος στη συλλογή μας CallExpressions για ανταλλαγή καθενός από τους κόμβους. Οι νέοι κόμβοι θα αντικαταστήσουν τα node.arguments με ένα νέο όρισμα, ένα αντικείμενο.

Ανταλλάξτε εύκολα τα επιχειρήματα της μεθόδου με το jscodeshift!

Αλλαγή υπογραφών μεθόδου με το «Replwith ()» και ανταλλαγή ολόκληρων κόμβων.

Ας το δοκιμάσουμε με ένα απλό αντικείμενο για να βεβαιωθούμε ότι γνωρίζουμε πώς λειτουργεί πριν χρησιμοποιήσουμε τις σωστές τιμές:

.replaceWith(nodePath => { const { node } = nodePath; node.arguments = [{ foo: 'bar' }]; return node; })

Όταν το εκτελέσουμε (jscodeshift -t signature-change.js signature-change.input.js -d -p), ο μετασχηματισμός θα εκραγεί με:

ERR signature-change.input.js Transformation error Error: {foo: bar} does not match type Printable

Αποδεικνύεται ότι δεν μπορούμε απλώς να μπλοκάρουμε απλά αντικείμενα στους κόμβους AST μας. Αντ 'αυτού, πρέπει να χρησιμοποιήσουμε τους κατασκευαστές για να δημιουργήσουμε κατάλληλους κόμβους.

Σχετίζεται με: Προσλάβετε το κορυφαίο 3% των ανεξάρτητων προγραμματιστών Javascript.

Κατασκευαστές κόμβων

Οι κατασκευαστές μας επιτρέπουν να δημιουργούμε σωστά νέους κόμβους. παρέχονται από ast-types και εμφανίστηκε μέσω του jscodeshift. Ελέγχουν αυστηρά ότι οι διαφορετικοί τύποι κόμβων έχουν δημιουργηθεί σωστά, κάτι που μπορεί να είναι απογοητευτικό όταν χαράζετε ένα ρολό, αλλά τελικά, αυτό είναι καλό. Για να καταλάβετε πώς να χρησιμοποιείτε τους κατασκευαστές, υπάρχουν δύο πράγματα που πρέπει να έχετε υπόψη:

Όλοι οι διαθέσιμοι τύποι κόμβων AST ορίζονται στο φάκελο def του ast-types github project , κυρίως στο core.js Υπάρχουν κατασκευαστές για όλους τους τύπους κόμβων AST, αλλά χρησιμοποιούν καμήλα έκδοση του τύπου κόμβου, όχι pascal-case . (Αυτό δεν αναφέρεται ρητά, αλλά μπορείτε να δείτε ότι ισχύει στην περίπτωση πηγή ast-types

Εάν χρησιμοποιήσουμε τον AST Explorer με ένα παράδειγμα αυτού που θέλουμε να είναι το αποτέλεσμα, μπορούμε να το συνδυάσουμε αρκετά εύκολα. Στην περίπτωσή μας, θέλουμε το νέο μεμονωμένο όρισμα να είναι ObjectExpression με πολλές ιδιότητες. Κοιτάζοντας τους ορισμούς τύπων που αναφέρονται παραπάνω, μπορούμε να δούμε τι συνεπάγεται αυτό:

def('ObjectExpression') .bases('Expression') .build('properties') .field('properties', [def('Property')]); def('Property') .bases('Node') .build('kind', 'key', 'value') .field('kind', or('init', 'get', 'set')) .field('key', or(def('Literal'), def('Identifier'))) .field('value', def('Expression'));

Έτσι, ο κώδικας για τη δημιουργία ενός κόμβου AST για το {foo: ‘bar’} θα μοιάζει με:

j.objectExpression([ j.property( 'init', j.identifier('foo'), j.literal('bar') ) ]);

Πάρτε αυτόν τον κωδικό και συνδέστε τον στον μετασχηματισμό μας έτσι:

.replaceWith(nodePath => { const { node } = nodePath; const object = j.objectExpression([ j.property( 'init', j.identifier('foo'), j.literal('bar') ) ]); node.arguments = [object]; return node; })

Τρέχοντας αυτό μας δίνει το αποτέλεσμα:

import car from 'car'; const suv = car.factory({ foo: 'bar' }); const truck = car.factory({ foo: 'bar' });

Τώρα που ξέρουμε πώς να δημιουργήσουμε έναν σωστό κόμβο AST, είναι εύκολο να βρούμε τα παλιά επιχειρήματα και να δημιουργήσουμε ένα νέο αντικείμενο για χρήση. Εδώ είναι τι signature-change.js το αρχείο μοιάζει τώρα:

//signature-change.js export default (fileInfo, api) => { const j = api.jscodeshift; const root = j(fileInfo.source); // find declaration for 'car' import const importDeclaration = root.find(j.ImportDeclaration, { source: { type: 'Literal', value: 'car', }, }); // get the local name for the imported module const localName = importDeclaration.find(j.Identifier) .get(0) .node.name; // current order of arguments const argKeys = [ 'color', 'make', 'model', 'year', 'miles', 'bedliner', 'alarm', ]; // find where `.factory` is being called return root.find(j.CallExpression, { callee: { type: 'MemberExpression', object: { name: localName, }, property: { name: 'factory', }, } }) .replaceWith(nodePath => { const { node } = nodePath; // use a builder to create the ObjectExpression const argumentsAsObject = j.objectExpression( // map the arguments to an Array of Property Nodes node.arguments.map((arg, i) => j.property( 'init', j.identifier(argKeys[i]), j.literal(arg.value) ) ) ); // replace the arguments with our new ObjectExpression node.arguments = [argumentsAsObject]; return node; }) // specify print options for recast .toSource({ quote: 'single', trailingComma: true }); };

Εκτελέστε τον μετασχηματισμό (jscodeshift -t signature-change.js signature-change.input.js -d -p) και θα δούμε ότι οι υπογραφές έχουν ενημερωθεί όπως αναμενόταν:

εύρεση διαρροών μνήμης στη java
import car from 'car'; const suv = car.factory({ color: 'white', make: 'Kia', model: 'Sorento', year: 2010, miles: 50000, bedliner: null, alarm: true, }); const truck = car.factory({ color: 'silver', make: 'Toyota', model: 'Tacoma', year: 2006, miles: 100000, bedliner: true, alarm: true, });

Codemods με ανακεφαλαίωση jscodeshift

Χρειάστηκε λίγος χρόνος και προσπάθεια για να φτάσουμε σε αυτό το σημείο, αλλά τα οφέλη είναι τεράστια όταν αντιμετωπίζουμε μαζική αναδιαμόρφωση. Η διανομή ομάδων αρχείων σε διαφορετικές διαδικασίες και η παράλληλη εκτέλεση τους είναι κάτι που ξεχωρίζει το jscodeshift, επιτρέποντάς σας να εκτελείτε σύνθετους μετασχηματισμούς σε μια τεράστια βάση κώδικα σε δευτερόλεπτα. Καθώς γίνετε πιο ικανοί με τα κωδικοκώδικα, θα αρχίσετε να επανατοποθετείτε υπάρχοντα σενάρια (όπως το reposit-codemod github αποθετήριο ή να γράψετε τη δική σας για κάθε είδους εργασίες, και αυτό θα κάνει εσάς, την ομάδα σας και τους χρήστες πακέτων σας πιο αποτελεσματικούς.

Fintech και Banks: Πώς μπορεί ο τραπεζικός κλάδος να ανταποκριθεί στην απειλή της διαταραχής;

Διαδικασίες Χρηματοδότησης

Fintech και Banks: Πώς μπορεί ο τραπεζικός κλάδος να ανταποκριθεί στην απειλή της διαταραχής;
Χρησιμοποιούνται οι 10 κορυφαίοι σχεδιαστές UX παραδοτέων

Χρησιμοποιούνται οι 10 κορυφαίοι σχεδιαστές UX παραδοτέων

Σχεδιασμός Ux

Δημοφιλείς Αναρτήσεις
Πώς να επιλέξετε το καλύτερο πλαίσιο Front-End
Πώς να επιλέξετε το καλύτερο πλαίσιο Front-End
Χρειάζεστε έναν ήρωα: Ο υπεύθυνος έργου
Χρειάζεστε έναν ήρωα: Ο υπεύθυνος έργου
Πώς να βελτιώσετε την απόδοση της εφαρμογής ASP.NET στο Web Farm με προσωρινή αποθήκευση
Πώς να βελτιώσετε την απόδοση της εφαρμογής ASP.NET στο Web Farm με προσωρινή αποθήκευση
Οι δοκιμασμένοι και αληθινοί νόμοι του UX (με Infographic)
Οι δοκιμασμένοι και αληθινοί νόμοι του UX (με Infographic)
Ανώτερος συνεργάτης πελάτη, υγειονομική περίθαλψη και βιοεπιστήμες
Ανώτερος συνεργάτης πελάτη, υγειονομική περίθαλψη και βιοεπιστήμες
 
Η άνοδος των αυτοματοποιημένων συναλλαγών: Μηχανές που εμπορεύονται το S&P 500
Η άνοδος των αυτοματοποιημένων συναλλαγών: Μηχανές που εμπορεύονται το S&P 500
10 πιο κοινές ευπάθειες ασφαλείας στον Ιστό
10 πιο κοινές ευπάθειες ασφαλείας στον Ιστό
Σκέψεις για τη συγκέντρωση του ιδιωτικού σας αμοιβαίου κεφαλαίου
Σκέψεις για τη συγκέντρωση του ιδιωτικού σας αμοιβαίου κεφαλαίου
Διευθυντής έργου και διαχείρισης προϊόντων
Διευθυντής έργου και διαχείρισης προϊόντων
Η σημασία της διατήρησης πελατών - μια εμπειρική μελέτη
Η σημασία της διατήρησης πελατών - μια εμπειρική μελέτη
Δημοφιλείς Αναρτήσεις
  • Παραδείγματα αρχών Gestalt στην πραγματική ζωή
  • πίνακας διάθεσης στο σχεδιασμό μόδας
  • πώς να φτιάξετε ένα discord bot java
  • Οι ελαστικότητες της ζήτησης ως προς τις τιμές είναι ιδιαίτερα χρήσιμες για τους διαχειριστές
  • κίνηση στις αρχές του σχεδιασμού
  • Ποιο από τα παρακάτω δεν αποτελεί αρχή Gestalt της αντιληπτικής οργάνωσης;
  • πώς να φτιάξετε λογιστικό σχέδιο
Κατηγορίες
  • Επιστήμη Δεδομένων Και Βάσεις Δεδομένων
  • Κατανεμημένες Ομάδες
  • Ευκίνητο Ταλέντο
  • Κερδοφορία & Αποδοτικότητα
  • © 2022 | Ολα Τα Δικαιώματα Διατηρούνται

    portaldacalheta.pt