SlideShare a Scribd company logo
1 of 59
Download to read offline
Crossfile Codemodding
with Joshua Lawrence
Joshua Lawrence
Sr. Software Engineer @LinkedIn
Developer Experience Team


Centralized Release Tool “CRT” - Internal CI/CD UI


Working with Ember for six years


Codemod n00b
Native


Classes
Engines
Angle


Brackets
Qunit
ES6


Modules
PODs
CHECKING
TYPE
ARGUMENT
Life Without Component Argument Type Checking
// ember-mascot usage


<EmberMascot @name={{this.name}} @likes={{this.likes}} />
Are there any other args
that I can/should provide?
Is this a number? Boolean?
An array of strings?
Probably a string
// ember-mascot.hbs


<p>{{this.name}}</p>


<p>{{this.likeCount}}</p>


<ul>


{{#each this.likes as |like|}}


<MascotLike @like={{like}} />


{{/each}}


</ul>
Life Without Component Argument Type Checking
Is this an argument with a default value


or a computed prop?
What is this an array of?
JSDoc Basic information for devs, but became
inaccurate over time
Verbose and lacks some features of argument
decorators
Uses modern patterns, is powerful and flexible,
doesn’t distract from component logic
ember-prop-types
ember-decorators/argument
Type Checking via “ember-decorators/argument”
// ember-mascot.hbs


<p>{{this.name}}</p>


<p>{{this.likeCount}}</p>


<ul>


{{#each this.likes as |like|}}


<MascotLike @like={{like}} />


{{/each}}


</ul>
// ember-mascot.js


export default class EmberMascot extends Component {


@argument(‘string’)


name = ‘’;


@argument(‘number’)


likeCount = 0;


@argument(shapeOf({


user: ‘string’,


date: Date


}))


likes;


}
Ditch type checking?


Brute force update?


Regex find and replace?


Stay on Ember 3.12 forever?
?
Ember.js Skill
GitHub Followers
Commits
Robert Jackson
@rwjblue
Chris Garrett
@pzuraq
Disclaimer: These stats are completely made up, but these guys are legit
ember-
argument-types
github.com/pzuraq/ember-
argument-types
// ember-mascot.hbs


{{arg-type @name (optional “string”)}}


{{arg-type @likeCount (optional “number”)}}


{{arg-type @likes (array-of


(shape-of


user=“string”


date=“date”


))


}}


<p>{{this.name}}</p>


<p>{{this.likeCount}}</p>


<ul>


{{#each this.likes as |like|}}


<MascotLike @like={{like}} />


{{/each}}


</ul>
ember-codemods
github.com/ember-codemods
jscodeshift
github.com/facebook/
jscodeshift
jscodeshift is a toolkit for running
codemods over multiple JavaScript or
TypeScript files.
…bring your own docs.
Input


source code
Mutate AST
Parse into


an AST
Convert to
source


and save
Lifecycle of a codemod
HTML DOM
JS AST
Can you codemod from


one file to another?
JS JS
HBS
codemod-cli project
Three transforms are better than one
Map
Decorators


to


JSON
Use JSON


to build


Template
Helpers
Remove


Argument


Decorators
JSON HBS JS
// argument-decorators.input.js


class Foo extends Component {


@argument(‘string’)


stringArg;


@argument(‘number’)


numberArg;


}
Transform 1 - Input/Output
// argument-decorators.map.json


{


“argument-decorators.input”: {


“path”: “path/to/file”,


“args”: {


“stringArg”: {


“type”: “StringLiteral”,


“value”: “string”


},


“numberArg”: {


“type”: “StringLiteral”,


“value”: “number”


},


}


}


}
// argument-types.input.hbs


<p>{{@stringArg}}</p>


<p>{{@numberArg}}</p>
Transform 2 - Input/Output
// argument-types.output.js


{{arg-type @stringArg “string”}}


{{arg-type @numberArg “number”}}


<p>{{@stringArg}}</p>


<p>{{@numberArg}}</p>
// argument-decorators.input.js


class Foo extends Component {


// This is a string arg


@argument(‘string’)


stringArg;


// This is a number arg


@argument(‘number’)


numberArg;


}
Transform 3 - Input/Output
// argument-decorators.output.js


class Foo extends Component {


// This is a string arg


stringArg;


// This is a number arg


numberArg;


}
Convert
Decorators


to


JSON
Use JSON
> codemod-cli new <project-name>


> codemod-cli generate codemod <codemod-name>


> codemod-cli generate fixture <codemod-name> <fixture-name>
// codemod-cli project transform


input.find(j.ClassBody).forEach((classBody) => {


classBody.value.body.filter((classProp) => {});B


});A


Transform 1: Decorators to JSON
// AST Explorer: Input


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// AST Explorer: Parsed AST


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// codemod-cli project transform


input.find(j.ClassBody).forEach((classBody) => {


classBody.value.body.filter((classProp) => {});B


});A


Transform 1: Decorators to JSON
// AST Explorer: Input


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// AST Explorer: Parsed AST


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// codemod-cli project transform


input.find(j.ClassBody).forEach((classBody) => {


classBody.value.body.filter((classProp) => {});B


});A


Transform 1: Decorators to JSON
// AST Explorer: Input


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// AST Explorer: Parsed AST


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// codemod-cli project transform


input.find(j.ClassBody).forEach((classBody) => {


classBody.value.body.filter((classProp) => {});B


});A


Transform 1: Decorators to JSON
// AST Explorer: Input


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// AST Explorer: Parsed AST


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// codemod-cli project transform


input.find(j.ClassBody).forEach((classBody) => {


classBody.value.body.filter((classProp) => {});B


});A


Transform 1: Decorators to JSON
// AST Explorer: Input


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// AST Explorer: Parsed AST


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// codemod-cli project transform


input.find(j.ClassBody).forEach((classBody) => {


classBody.value.body.filter((classProp) => {


return classProp.decorators.some((decorator) => {});C


});B


});A


Transform 1: Decorators to JSON
// AST Explorer: Input


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// AST Explorer: Parsed AST


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// codemod-cli project transform


input.find(j.ClassBody).forEach((classBody) => {


classBody.value.body.filter((classProp) => {


return classProp.decorators.some((decorator) => {


return (


decorator.expression.type === 'CallExpression' &&


(decorator.expression.callee.name === 'type' ||


decorator.expression.callee.name === 'argument')


);


});C


});B


});A


Transform 1: Decorators to JSON
// AST Explorer: Input


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// AST Explorer: Parsed AST


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// codemod-cli project transform


input.find(j.ClassBody).forEach((classBody) => {


classBody.value.body.filter((classProp) => {


return classProp.decorators.some((decorator) => {


return (


decorator.expression.type === 'CallExpression' &&


(decorator.expression.callee.name === 'type' ||


decorator.expression.callee.name === 'argument')


);


});C


}).forEach(parseDecoratorArgs);B


});A


Transform 1: Decorators to JSON
// AST Explorer: Input


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// AST Explorer: Parsed AST


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// codemod-cli project transform


input.find(j.ClassBody).forEach((classBody) => {


classBody.value.body.filter((classProp) => {


return classProp.decorators.some((decorator) => {


return (


decorator.expression.type === 'CallExpression' &&


(decorator.expression.callee.name === 'type' ||


decorator.expression.callee.name === 'argument')


);


});C


}).forEach(parseDecoratorArgs);B


});A


fs.writeFileSync(


‘map.json’,


JSON.stringify(parsedDecorators, null, 2),


{ encoding: ‘utf8' }


);


Transform 1: Decorators to JSON
// AST Explorer: Input


class Foo extends Component {


@argument(‘string’)


stringArg;


}
// AST Explorer: Parsed AST


class Foo extends Component {


@argument(‘string’)


stringArg;


}
Multiple codemod passes with increasing scope
Test Fixtures
One Component
Directory with a
few components
All components
Convert
Decorators


to build


Template
Helpers
Remove
Argument


Decorators
JSON HBS JS
import { argument } from '@ember-
decorators/argument';


class Foo extends Component {


// This is a string arg


@someUnrelatedDecorator


@argument(‘string’)


stringArg;


}
Remove Argument Decorators
class Foo extends Component {


// This is a string arg


@someUnrelatedDecorator


stringArg;


}
Putting them all together
Map
Decorators


to


JSON
Use JSON


to build


Template
Helpers
Remove


Argument


Decorators
JSON HBS JS
github.com/ember-decorators/
argument-codemod
ember-decorators/
argument-codemod
> npx @ember-decorators/argument-codemod decorators-to-json ./app/components


> npx @ember-decorators/argument-codemod json-to-template ./app/templates/components


> npx @ember-decorators/argument-codemod decorators-cleanup ./app/components
Almost there…
Ember 3.20 Octane
Takeaways
Your code(mod)
doesn’t need to
be perfect
Sometimes you
have to be the
one to fix it
Don’t stop


at one
Opportunities to
improve tooling
THANK YOU!
Resources


https://github.com/ember-decorators/argument-codemod


https://github.com/pzuraq/ember-argument-types


https://github.com/rwjblue/codemod-cli


https://github.com/facebook/jscodeshift


https://github.com/ember-codemods
jwlawrence joshlawrence jlaw

More Related Content

What's hot

Denis Lebedev, Swift
Denis  Lebedev, SwiftDenis  Lebedev, Swift
Denis Lebedev, SwiftYandex
 
The Swift Compiler and Standard Library
The Swift Compiler and Standard LibraryThe Swift Compiler and Standard Library
The Swift Compiler and Standard LibrarySantosh Rajan
 
Scala + WattzOn, sitting in a tree....
Scala + WattzOn, sitting in a tree....Scala + WattzOn, sitting in a tree....
Scala + WattzOn, sitting in a tree....Raffi Krikorian
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of FlatteryJosé Paumard
 
Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelizationJava 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelizationJosé Paumard
 
CS4200 2019 | Lecture 3 | Parsing
CS4200 2019 | Lecture 3 | ParsingCS4200 2019 | Lecture 3 | Parsing
CS4200 2019 | Lecture 3 | ParsingEelco Visser
 
10 Sets of Best Practices for Java 8
10 Sets of Best Practices for Java 810 Sets of Best Practices for Java 8
10 Sets of Best Practices for Java 8Garth Gilmour
 
Cocoa Design Patterns in Swift
Cocoa Design Patterns in SwiftCocoa Design Patterns in Swift
Cocoa Design Patterns in SwiftMichele Titolo
 
Zend Certification Preparation Tutorial
Zend Certification Preparation TutorialZend Certification Preparation Tutorial
Zend Certification Preparation TutorialLorna Mitchell
 

What's hot (19)

Java Full Throttle
Java Full ThrottleJava Full Throttle
Java Full Throttle
 
Denis Lebedev, Swift
Denis  Lebedev, SwiftDenis  Lebedev, Swift
Denis Lebedev, Swift
 
X Path
X PathX Path
X Path
 
Code generating beans in Java
Code generating beans in JavaCode generating beans in Java
Code generating beans in Java
 
The Swift Compiler and Standard Library
The Swift Compiler and Standard LibraryThe Swift Compiler and Standard Library
The Swift Compiler and Standard Library
 
Scala + WattzOn, sitting in a tree....
Scala + WattzOn, sitting in a tree....Scala + WattzOn, sitting in a tree....
Scala + WattzOn, sitting in a tree....
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelizationJava 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelization
 
Swift Introduction
Swift IntroductionSwift Introduction
Swift Introduction
 
Getting rid of backtracking
Getting rid of backtrackingGetting rid of backtracking
Getting rid of backtracking
 
CS4200 2019 | Lecture 3 | Parsing
CS4200 2019 | Lecture 3 | ParsingCS4200 2019 | Lecture 3 | Parsing
CS4200 2019 | Lecture 3 | Parsing
 
10 Sets of Best Practices for Java 8
10 Sets of Best Practices for Java 810 Sets of Best Practices for Java 8
10 Sets of Best Practices for Java 8
 
Cocoa Design Patterns in Swift
Cocoa Design Patterns in SwiftCocoa Design Patterns in Swift
Cocoa Design Patterns in Swift
 
Java 8 ​and ​Best Practices
Java 8 ​and ​Best PracticesJava 8 ​and ​Best Practices
Java 8 ​and ​Best Practices
 
Intro to Perl and Bioperl
Intro to Perl and BioperlIntro to Perl and Bioperl
Intro to Perl and Bioperl
 
Linq intro
Linq introLinq intro
Linq intro
 
Clean code slide
Clean code slideClean code slide
Clean code slide
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
 
Zend Certification Preparation Tutorial
Zend Certification Preparation TutorialZend Certification Preparation Tutorial
Zend Certification Preparation Tutorial
 

Similar to EmberConf 2021 - Crossfile Codemodding with Joshua Lawrence

Php Reusing Code And Writing Functions
Php Reusing Code And Writing FunctionsPhp Reusing Code And Writing Functions
Php Reusing Code And Writing Functionsmussawir20
 
Naïveté vs. Experience
Naïveté vs. ExperienceNaïveté vs. Experience
Naïveté vs. ExperienceMike Fogus
 
Pxb For Yapc2008
Pxb For Yapc2008Pxb For Yapc2008
Pxb For Yapc2008maximgrp
 
Ast transformations
Ast transformationsAst transformations
Ast transformationsHamletDRC
 
The Java Script Programming Language
The  Java Script  Programming  LanguageThe  Java Script  Programming  Language
The Java Script Programming Languagezone
 
Javascript by Yahoo
Javascript by YahooJavascript by Yahoo
Javascript by Yahoobirbal
 
The JavaScript Programming Language
The JavaScript Programming LanguageThe JavaScript Programming Language
The JavaScript Programming LanguageRaghavan Mohan
 
Les origines de Javascript
Les origines de JavascriptLes origines de Javascript
Les origines de JavascriptBernard Loire
 
AST Transformations
AST TransformationsAST Transformations
AST TransformationsHamletDRC
 
STC 2016 Programming Language Storytime
STC 2016 Programming Language StorytimeSTC 2016 Programming Language Storytime
STC 2016 Programming Language StorytimeSarah Kiniry
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the ASTJarrod Overson
 
Применение паттерна Page Object для автоматизации веб сервисов - новый взгляд
Применение паттерна Page Object для автоматизации веб сервисов - новый взглядПрименение паттерна Page Object для автоматизации веб сервисов - новый взгляд
Применение паттерна Page Object для автоматизации веб сервисов - новый взглядCOMAQA.BY
 
JCConf 2021 - Java17: The Next LTS
JCConf 2021 - Java17: The Next LTSJCConf 2021 - Java17: The Next LTS
JCConf 2021 - Java17: The Next LTSJoseph Kuo
 

Similar to EmberConf 2021 - Crossfile Codemodding with Joshua Lawrence (20)

Php Reusing Code And Writing Functions
Php Reusing Code And Writing FunctionsPhp Reusing Code And Writing Functions
Php Reusing Code And Writing Functions
 
Lettering js
Lettering jsLettering js
Lettering js
 
Naïveté vs. Experience
Naïveté vs. ExperienceNaïveté vs. Experience
Naïveté vs. Experience
 
Pxb For Yapc2008
Pxb For Yapc2008Pxb For Yapc2008
Pxb For Yapc2008
 
Einführung in TypeScript
Einführung in TypeScriptEinführung in TypeScript
Einführung in TypeScript
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 
The Java Script Programming Language
The  Java Script  Programming  LanguageThe  Java Script  Programming  Language
The Java Script Programming Language
 
Javascript by Yahoo
Javascript by YahooJavascript by Yahoo
Javascript by Yahoo
 
The JavaScript Programming Language
The JavaScript Programming LanguageThe JavaScript Programming Language
The JavaScript Programming Language
 
Javascript
JavascriptJavascript
Javascript
 
Les origines de Javascript
Les origines de JavascriptLes origines de Javascript
Les origines de Javascript
 
Javascript2839
Javascript2839Javascript2839
Javascript2839
 
Json
JsonJson
Json
 
AST Transformations
AST TransformationsAST Transformations
AST Transformations
 
STC 2016 Programming Language Storytime
STC 2016 Programming Language StorytimeSTC 2016 Programming Language Storytime
STC 2016 Programming Language Storytime
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
 
Antlr V3
Antlr V3Antlr V3
Antlr V3
 
Применение паттерна Page Object для автоматизации веб сервисов - новый взгляд
Применение паттерна Page Object для автоматизации веб сервисов - новый взглядПрименение паттерна Page Object для автоматизации веб сервисов - новый взгляд
Применение паттерна Page Object для автоматизации веб сервисов - новый взгляд
 
JCConf 2021 - Java17: The Next LTS
JCConf 2021 - Java17: The Next LTSJCConf 2021 - Java17: The Next LTS
JCConf 2021 - Java17: The Next LTS
 

Recently uploaded

"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 

Recently uploaded (20)

"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 

EmberConf 2021 - Crossfile Codemodding with Joshua Lawrence

  • 2. Joshua Lawrence Sr. Software Engineer @LinkedIn Developer Experience Team Centralized Release Tool “CRT” - Internal CI/CD UI Working with Ember for six years Codemod n00b
  • 4.
  • 6. Life Without Component Argument Type Checking // ember-mascot usage <EmberMascot @name={{this.name}} @likes={{this.likes}} /> Are there any other args that I can/should provide? Is this a number? Boolean? An array of strings? Probably a string
  • 7. // ember-mascot.hbs <p>{{this.name}}</p> <p>{{this.likeCount}}</p> <ul> {{#each this.likes as |like|}} <MascotLike @like={{like}} /> {{/each}} </ul> Life Without Component Argument Type Checking Is this an argument with a default value or a computed prop? What is this an array of?
  • 8. JSDoc Basic information for devs, but became inaccurate over time Verbose and lacks some features of argument decorators Uses modern patterns, is powerful and flexible, doesn’t distract from component logic ember-prop-types ember-decorators/argument
  • 9. Type Checking via “ember-decorators/argument” // ember-mascot.hbs <p>{{this.name}}</p> <p>{{this.likeCount}}</p> <ul> {{#each this.likes as |like|}} <MascotLike @like={{like}} /> {{/each}} </ul> // ember-mascot.js export default class EmberMascot extends Component { @argument(‘string’) name = ‘’; @argument(‘number’) likeCount = 0; @argument(shapeOf({ user: ‘string’, date: Date })) likes; }
  • 10.
  • 11. Ditch type checking? Brute force update? Regex find and replace? Stay on Ember 3.12 forever? ?
  • 12. Ember.js Skill GitHub Followers Commits Robert Jackson @rwjblue Chris Garrett @pzuraq Disclaimer: These stats are completely made up, but these guys are legit
  • 13. ember- argument-types github.com/pzuraq/ember- argument-types // ember-mascot.hbs {{arg-type @name (optional “string”)}} {{arg-type @likeCount (optional “number”)}} {{arg-type @likes (array-of (shape-of user=“string” date=“date” )) }} <p>{{this.name}}</p> <p>{{this.likeCount}}</p> <ul> {{#each this.likes as |like|}} <MascotLike @like={{like}} /> {{/each}} </ul>
  • 15.
  • 16. jscodeshift github.com/facebook/ jscodeshift jscodeshift is a toolkit for running codemods over multiple JavaScript or TypeScript files. …bring your own docs.
  • 17. Input source code Mutate AST Parse into an AST Convert to source and save Lifecycle of a codemod
  • 19. Can you codemod from one file to another? JS JS HBS
  • 20. codemod-cli project Three transforms are better than one Map Decorators to JSON Use JSON to build Template Helpers Remove Argument Decorators JSON HBS JS
  • 21. // argument-decorators.input.js class Foo extends Component { @argument(‘string’) stringArg; @argument(‘number’) numberArg; } Transform 1 - Input/Output // argument-decorators.map.json { “argument-decorators.input”: { “path”: “path/to/file”, “args”: { “stringArg”: { “type”: “StringLiteral”, “value”: “string” }, “numberArg”: { “type”: “StringLiteral”, “value”: “number” }, } } }
  • 22. // argument-types.input.hbs <p>{{@stringArg}}</p> <p>{{@numberArg}}</p> Transform 2 - Input/Output // argument-types.output.js {{arg-type @stringArg “string”}} {{arg-type @numberArg “number”}} <p>{{@stringArg}}</p> <p>{{@numberArg}}</p>
  • 23. // argument-decorators.input.js class Foo extends Component { // This is a string arg @argument(‘string’) stringArg; // This is a number arg @argument(‘number’) numberArg; } Transform 3 - Input/Output // argument-decorators.output.js class Foo extends Component { // This is a string arg stringArg; // This is a number arg numberArg; }
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31. > codemod-cli new <project-name> > codemod-cli generate codemod <codemod-name> > codemod-cli generate fixture <codemod-name> <fixture-name>
  • 32. // codemod-cli project transform input.find(j.ClassBody).forEach((classBody) => { classBody.value.body.filter((classProp) => {});B });A Transform 1: Decorators to JSON // AST Explorer: Input class Foo extends Component { @argument(‘string’) stringArg; } // AST Explorer: Parsed AST class Foo extends Component { @argument(‘string’) stringArg; }
  • 33. // codemod-cli project transform input.find(j.ClassBody).forEach((classBody) => { classBody.value.body.filter((classProp) => {});B });A Transform 1: Decorators to JSON // AST Explorer: Input class Foo extends Component { @argument(‘string’) stringArg; } // AST Explorer: Parsed AST class Foo extends Component { @argument(‘string’) stringArg; }
  • 34. // codemod-cli project transform input.find(j.ClassBody).forEach((classBody) => { classBody.value.body.filter((classProp) => {});B });A Transform 1: Decorators to JSON // AST Explorer: Input class Foo extends Component { @argument(‘string’) stringArg; } // AST Explorer: Parsed AST class Foo extends Component { @argument(‘string’) stringArg; }
  • 35. // codemod-cli project transform input.find(j.ClassBody).forEach((classBody) => { classBody.value.body.filter((classProp) => {});B });A Transform 1: Decorators to JSON // AST Explorer: Input class Foo extends Component { @argument(‘string’) stringArg; } // AST Explorer: Parsed AST class Foo extends Component { @argument(‘string’) stringArg; }
  • 36. // codemod-cli project transform input.find(j.ClassBody).forEach((classBody) => { classBody.value.body.filter((classProp) => {});B });A Transform 1: Decorators to JSON // AST Explorer: Input class Foo extends Component { @argument(‘string’) stringArg; } // AST Explorer: Parsed AST class Foo extends Component { @argument(‘string’) stringArg; }
  • 37. // codemod-cli project transform input.find(j.ClassBody).forEach((classBody) => { classBody.value.body.filter((classProp) => { return classProp.decorators.some((decorator) => {});C });B });A Transform 1: Decorators to JSON // AST Explorer: Input class Foo extends Component { @argument(‘string’) stringArg; } // AST Explorer: Parsed AST class Foo extends Component { @argument(‘string’) stringArg; }
  • 38. // codemod-cli project transform input.find(j.ClassBody).forEach((classBody) => { classBody.value.body.filter((classProp) => { return classProp.decorators.some((decorator) => { return ( decorator.expression.type === 'CallExpression' && (decorator.expression.callee.name === 'type' || decorator.expression.callee.name === 'argument') ); });C });B });A Transform 1: Decorators to JSON // AST Explorer: Input class Foo extends Component { @argument(‘string’) stringArg; } // AST Explorer: Parsed AST class Foo extends Component { @argument(‘string’) stringArg; }
  • 39. // codemod-cli project transform input.find(j.ClassBody).forEach((classBody) => { classBody.value.body.filter((classProp) => { return classProp.decorators.some((decorator) => { return ( decorator.expression.type === 'CallExpression' && (decorator.expression.callee.name === 'type' || decorator.expression.callee.name === 'argument') ); });C }).forEach(parseDecoratorArgs);B });A Transform 1: Decorators to JSON // AST Explorer: Input class Foo extends Component { @argument(‘string’) stringArg; } // AST Explorer: Parsed AST class Foo extends Component { @argument(‘string’) stringArg; }
  • 40. // codemod-cli project transform input.find(j.ClassBody).forEach((classBody) => { classBody.value.body.filter((classProp) => { return classProp.decorators.some((decorator) => { return ( decorator.expression.type === 'CallExpression' && (decorator.expression.callee.name === 'type' || decorator.expression.callee.name === 'argument') ); });C }).forEach(parseDecoratorArgs);B });A fs.writeFileSync( ‘map.json’, JSON.stringify(parsedDecorators, null, 2), { encoding: ‘utf8' } ); Transform 1: Decorators to JSON // AST Explorer: Input class Foo extends Component { @argument(‘string’) stringArg; } // AST Explorer: Parsed AST class Foo extends Component { @argument(‘string’) stringArg; }
  • 41. Multiple codemod passes with increasing scope Test Fixtures One Component Directory with a few components All components
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 53. import { argument } from '@ember- decorators/argument'; class Foo extends Component { // This is a string arg @someUnrelatedDecorator @argument(‘string’) stringArg; } Remove Argument Decorators class Foo extends Component { // This is a string arg @someUnrelatedDecorator stringArg; }
  • 54. Putting them all together Map Decorators to JSON Use JSON to build Template Helpers Remove Argument Decorators JSON HBS JS
  • 55. github.com/ember-decorators/ argument-codemod ember-decorators/ argument-codemod > npx @ember-decorators/argument-codemod decorators-to-json ./app/components > npx @ember-decorators/argument-codemod json-to-template ./app/templates/components > npx @ember-decorators/argument-codemod decorators-cleanup ./app/components
  • 58. Takeaways Your code(mod) doesn’t need to be perfect Sometimes you have to be the one to fix it Don’t stop at one Opportunities to improve tooling