Since our last post, “Mama Ali’s new tool eases the pain of batch modifying project code,” we’ve been getting questions from people who are doing AST code replacements with GoGoCode: How do I get variables? How do I batch replace? How do I insert Spaces? How do I replace it? What’s wrong with my matching? … So the little sister overnight sorted out 30 code replacement tips, let everyone a breath to learn! Learn not to also doesn’t matter, welcome to add group hand bag church ~ nail group: 34266233; Qq group: 735216094 Github: github.com/thx/gogocod… New project to star support O (////▽////) Q website: gogocode. IO

Base type obtain and operate

01. Get variables

// Get all variables
$(code)
  .find('$_ $')
  .each(item= > {
    console.log(item.match)
  })

// Variable name list
$(code)
  .find('list')
Copy the code

02. Change the value of a variable

// Get the fetch variable and change its name to request
const res = $(`const fetch = () => {}; const noChange = 'fetch'`)
  .find('fetch')
  .each(item= > {
    item.attr('name'.'request')		// Any node attribute can be obtained or modified by attr
  })
  .root()
  .generate()
Copy the code

03. Get a string

// Get all strings
$(code)
  .find(` '$_ $' `)
  .each(item= > {
      console.log(item.match)	
  })

// Get the string 'list/get'
$(code)
  .find(`'getList'`)
  .each(item= > {
      console.log(item.node)	
  })
Copy the code

04. Get the assignment statement

Assignment and Declaration statements need to be separated
// Get all assignment statements
$(code)
  .find(` $_ $1 = $_ $2 `)
  .each(item= > {
    console.log(item.match[1])
    console.log(item.match[2])})// Get the assignment statement to list
$(code)
  .find('list = $_$')
  .each(item= > {
    console.log(item.match[0])})// Get the assignment statement for the color property in the CAR object
$(code)
  .find('car.color = $_$')

// Get the assignment statement for the color property in any object
$(code)
  .find('$_$1.color = $_$2')

// Get the name of the variable assigned by [1, 2]
$(code)
  .find('$_$ = [1, 2]')
Copy the code

05. Get the definition statement

// Get all definitions, including variable definitions and function definitions
$(code)
    .find(`var $_$1 = $_$2`)

// Get the definition statement for list
$(code)
    .find([`var list = $_$`.`let list = $_$`.`const list = $_$`])
Copy the code

06. Get a variable definition in a scope

// Find the create function and get the type variable definition inside it

$(code)
    .find('function() create() {}')
    .find('let type = $_$')

// After finding the create function, return the global to obtain the type variable definition or other operations
$(code)
    .find('function() create() {}')
    .each(item= > {})
    .root()								// Back to the global
    .find('let type = $_$')
Copy the code

07. Get the class definition

// Get all class definitions
$(code)
  .find(`class $_$ {}`)

// Get the definition of the Car class
$(code)
  .find(`class Car {}`)

// Get the Car class definition with the color\size attribute
$(code)
  .find(`class Car { color = $_$c size = $_$s }`)
  .each(item= > {
    item.match['c']
    item.match['s']})Copy the code

08. Get the TS type definition

// Get the statement of type CheckBoxProps
$(code)
  .find('CheckBoxProps')    // It may be a variable name or a type definition
  .each(item= > {
      if (item.parent().node.type == 'TSTypeReference') {
          TSTypeReference = TSTypeReference = TSTypeReference}})// Get the variable definition of type CheckBoxProps
$(code)
  .find('let $_$1:CheckBoxProps = $_$2')
  .each(item= > {
    item.match[1]     / / variable names
    item.match[2]     / / variable values
  })

// Get the arrow function * with an input of type CheckBoxProps
$(code)
  .find('($_$: CheckBoxProps) => {}')
  .each(item= > {
    item.match    / / into the refs
    item.node     // Arrow function complete node
  })
Copy the code

Function – related fetching and operations

10. Get the function definition

$(code)
  .find(`function $_$() {}`)
  .each(item= > {
    item.match[0] / / the function name
    item.node     // Function complete node
  })

// Get the arrow function
$(code)
  .find(` ` () = > {})

// Get the arrow function that takes type
$(code)
  .find(`(type) => {}`)
Copy the code

11. Get the function content determined by the function name

methods1$(code).find($(code).find($(code))`function greet() { $_$ }`)
  .each(item= > {
    item.match[0] [0].value		// The contents of the function
  	item.match[0] [0].node			// The ast node corresponding to the function content}) method2$(code).find(attr() $(code).find()`function greet() {}`)
  .each(item= > {
    $(item.attr('body')).generate()			// The contents of the function
  	item.attr('body')										// The ast node corresponding to the function content
  })
Copy the code

Get the function that contains a statement

// Method 1: The selector gets the function containing this.requester
$(code)
  .find(`function $_$() { this.requester }`)


// Method 2: Obtain all functions and determine whether this. Requester is contained inside
$(code)
  .find(`function $_$() { }`)
  .each(item= > {
    if (item.has('this.requester')) {
      // Check whether the node contains this.requester}})Copy the code

13. Get the function call

// Get all function calls
$(code)
	.find('$_ $()')
	.each(item= > {
	  item.match		/ / the function name
  	  item.node			// The ast node corresponding to the function
  	  item.attr('arguments')		// The incoming arguments to the call function
	})

// Get the function called with this
$(code)
	.find('this.$_$()')

// Get the call to the create function
$(code)
	.find('create()')
Copy the code

14. Modify function input parameters

alert({
  type: 'error'.content: 'Please fill in the required fields'.done: () = >{}})// Smooth out the type and content of the alert call

$(code)
  .replace(`alert({ type: $_$1, done: $_$3, content: $_$2})`.`alert( $_$1, $_$2, $_$3 )`)


// Insert this before the incoming arguments to the alert call
$(code).replace(`alert($$$)`.`alert(this, $$$)`)
Copy the code

15. Construct new nodes according to the original node structure

// This is still the case with the type and content of the alert call:

alert({
  type: 'error'.content: 'Please fill in the required fields'.done: () = > {}
})

$(code)
  .find(`alert({ type: $_$1, content: $_$2, done: $_$3 })`)
  .each(item= > {
    const typeValue = item.match[1] [0].value,
          contentValue = item.match[2] [0].value,
          doneValue = item.match[3] [0].value
    item.replaceBy($(`
      alert( ${typeValue}.${contentValue}.${doneValue} )
    `))})Copy the code

Object and property related acquisition and operation

16. Obtain object properties

// Get the function named greet inside the object
$(code)
  .find(`greet() {}`)
  .each(item= > {
    item.node     / / the greet method
    item.parent(1).node   // greet the outer object of the method
  })

// Get the property named greet inside the object
$(code)
  .find(`greet: $_$`)
Copy the code

17. Obtain the object

// Get the object containing the color attribute
$(code)
  .find(`{ color: $_$ }`)
  .each(item= > {
    item.node     // The object containing the color property
    item.match    / / color values
  })

// Get an object that contains color and whose color is green
$(code)
  .find(`{ color: 'green' }`)

// Get the object containing the init() {} member function
$(code)
  .find(`{ init() {} }`)

// Get the object named car
$(code)
  .find(`const car = $_$`)
  .each(item= > {
    // item.match is the node matched by the wildcard
    if (item.match[0] [0].node.type == 'ObjectExpression') {
      // Find the node to which car was assigned and check whether it is an object type}})Copy the code

18. Modify the properties of the object

const code = Page({
  onShow(){},data: {}})// Change the name of the onShow function in the first input to Page to render

    // Method 1: where $$$1 and $$$2 represent rest, capture the rest and do not change
    $(code)
      .replace(`Page({ onShow() { $$$1 }, $$$2 })`.`Page({ render() { $$$1 }, $$$2 })`)

    // Method 2: use match to change the child node attributes
    $(code).find(`Page({ $_$() { } })`)
      .each(item= > {
        if (item.match[0] [0].value == 'onShow') {
          item.match[0] [0].node.name = 'render'}})Copy the code

19. Conditionally modify the value of an object attribute

const map = { input: 'textarea' }		// Modify the map only when there is a map

const res = $(` const componentList = [{ index: 1, component: 'input' }, { index: 2, component: 'radio' }, { index: 3, component: 'checkbox' }]`)
.replace('component: $_$', (match= > {
  if (map[match[0] [0].value]) {
    return `component: ${map[match[0] [0].value]}`
  } else {
    return 'component: $_$'
  }
}))
.generate()
Copy the code

Insert a new property into the

Page({
  onShow(){},data: {}})// Insert init() {this.data = {}}$(code).replace()`Page({ $$$2 })`.`Page({ init() { this.data = {} }, $$$2 })`)

// Method 2: Use Append
$(code).find(`Page({})`)
  .each(item= > {
		$(item.attr('arguments.0')).append('properties'.`init() {}`)
  	// Page has arguments[0] as the first input object. Attr retrive this object and convert it to an AST instance.
  	The first argument of append is the second argument specifying where to insert it
  })
	.root()
	.generate()
Copy the code

Import/export related acquisition and operation

21. Get the import export statement

// Get all import statements
// include import x from 'xx'; import { x } from 'xx' ; import 'xx'
$(code)
  .find(`import $_$1 from '$_$2'`)
  // The second wildcard needs to be enclosed in quotes, because the import statement requires source to be a string


// Match import asynchron, such as import('@source/package/index').then()
$(code)
  .find(`import($_$)`)

// Match the ExportNameDeclaration statement
$(code)
  .find(`export $_$ from '@path/sth'`)


// Match the ExportAllDeclaration statement
$(code)
  .find(`export * from '@path/sth'`)

Copy the code

22. Get the import statement and modify the source

// Select * from 'bb/bb-plugin' where 'bb/bb-plugin' = 'gogocode';

$(code)
  .replace(`import $_$ from 'bb/bb-plugin'`.`import $_$ from 'gogocode'`)

// Get the module path containing 'bb/... 'and change to bb/gogocode/...
$(code)
  .find(`import $_$1 from '$_$2'`)
  .each(item= > {
    const source = item.match[2] [0].value;
    item.match[2] [0].node.value = source.replace('bb/'.'bb/gogocode/');
  })


// Source code:
// import { useContext, userLogger } from '@as/mdw-hk'
// Change the name of the useContext module from @as/ mdW-hk to useFContext
$(code).replace(`import { useContext, $$$ } from '@as/mdw-hk'`.`import { useFContext, $$$ } from '@as/mdw-hk'`)
// $$$indicates rest
Copy the code

Operations related to JSX labels

23. Change the JSX label name

// JSX content:
<View>
  <View name="1" class="active" />
  <View></View>
</View>

// Change the name of the View tag to div

$(code)
	.replace(`<View $$$1>$$$2</View>`.`<div $$$1>$$$2</div>`)
Copy the code

24. Modify JSX attributes

// JSX content:
<View>
  <View name="1" class="active" />
  <View name="1" id="key">text</View>
</View>

// Change the name="1" attribute of the View tag to type="input"

$(code)
	.replace(`<View name="1" $$$1>$$$2</View>`.`<View type="input" $$$1>$$$2</View>`)
Copy the code

Several complete cases

25. Batch convert all.js files in a folder

const glob = require('glob');
const$=require('gogocode');

glob('./code/**/*.js'.function (err, files) {
    files.forEach(function (file) { rewrite(file); })})function rewrite(filePath) {
    const newCode = $.loadFile(filePath)
    	.replace(`let $_$ = console.log()`.`let $_$ = void 0`)
    	.generate()
 		$.writeFile(newCode, filePath);
}
Copy the code

26. Insert a blank line after a line of code

Insert a blank line after all function definitions
// The blank line has no corresponding node in the AST. You can insert a string with a timestamp. The AST outputs a string and then globally replaces the timestamp string with null

const placeholder = `placeholderThe ${+new Date()}`;
$(code)
  .find('function $_$() {}')
  .after(placeholder)
  .root()
  .generate()
  .replace(new RegExp(placeholder, 'g'), ' ');
Copy the code

27. Delete a node

// Find the console.log() node and delete itmethods1:
$(code)
  .find('console.log()'). The remove () method2:
$(code).replace('console.log()'.' ')
Copy the code

28. Deconstruct assignment to es5 writing

Const {a,b = {b1},c = 3} = d; To a const da, a = b = db | | {b1}, c =, dc | | 3;

const res = $(`const {a,b = {b1},c = 3} = d`)
  .find('const { $_$1 = $_$2 } = $_$3')
  .each(item= > {
    const keyList = item.match[1].filter((item, i) = > i%2= =0)
    const obj = item.match[3] [0].value
    const newkeyList = keyList.map((key, i) = > {
      let dec = `${key.value} = ${obj}.${key.value}`
      if (item.match[2][i].value ! = key.value) { dec += ('| |' + item.match[2][i].value)
      }
      return dec
    })
    item.replaceBy(`const ${newkeyList.join(', ')}`)
  })
	.root()
  .generate()

Copy the code

29. Insert multiple pieces of code

$(code)
  .find(`function create() {}`)
  .each(item= > {
      $(item.attr('body')).append('body'.` let type = 'success' console.log('success') `)
  .root()
  .generate()
})
Copy the code

30. Get variables in an expression

$(`(a.b.c && b) || (c && d)`)
.find('$_ $')
.each(item= > {
  if (item.parent().node.type == 'MemberExpression' && item.parent(1).node.type ! ='MemberExpression') {
    // Output A.B.C as a whole instead of a \ b \ c
    console.log(item.parent().generate())
  } else if(item.parent().node.type ! ='MemberExpression') {
    // Output independent variables
    console.log(item.generate())
  }
})
// Output a.b.c\ b \ c \ d
Copy the code

More tips will be added on the website. If you have any questions or new questions about the above cases, please write them in the comments section and we will reply soon ~

There will be more AST code conversion articles, please continue to pay attention to ali Mom front end fast explosion.