Skip to content

Advanced utility for golang refactor based on DSL transformations.

License

Notifications You must be signed in to change notification settings

lwsanty/gofactor

Repository files navigation

gofactor

Advanced utility for golang refactor based on DSL transformations provided by bblfsh/sdk

Requirements

  • Go 1.13+

Build

Build the CLI:

  1. clone gofactor repo
git clone https://github.com/lwsanty/gofactor
  1. build CLI
go install ./cmd/gofactor

Usage example

Imagine you have a piece of code

package main

import "fmt"

func main() {
	var (
		i int
		X int
		j int
	)

	if i%2 == 0 {
		i = 5
	}

	if X%2 == 0 {
		X = 5
	}

	fmt.Println(i)

	if i%2 == 0 {
		i = 5
	}

	if j%2 == 0 {
		j = 5
	}
}

func a(i, X int) {
	if i%2 == 0 {
		i = 5
	}

	if X%2 == 0 {
		X = 5
	}

	fmt.Println(i)

	if i%2 == 0 {
		i = 5
	}

	if X%2 == 0 {
		X = 5
	}
}

And you want to replace all code patterns like

if i%2 == 0 {
    i = 5
}

if X%2 == 0 {
    X = 5
}

to

if i%2 == 1 {
    i = 1
} else {
    X = 1
}

Here's where gofactor tool comes for help.

Save the "before" snippet to before.txt, "after" snippet to an after.txt file, and run:

gofactor --before before.txt --after after.txt some_file.go

Result

package main

import "fmt"

func main() {
	var (
		i int
		X int
		j int
	)
	if i%2 == 1 {
		i = 1
	} else {
		X = 1
	}
	fmt.Println(i)
	if i%2 == 1 {
		i = 1
	} else {
		j = 1
	}
}
func a(i, X int) {
	if i%2 == 1 {
		i = 1
	} else {
		X = 1
	}
	fmt.Println(i)
	if i%2 == 1 {
		i = 1
	} else {
		X = 1
	}
}

Usage as a library

It is also possible to use the tools as a library.

  1. Init refactor object
refactor, err := gofactor.NewRefactor(beforeSnippet, afterSnippet)
if err != nil {
    log.Error(err)
    os.Exit(1)
}
  1. Apply generated transformations to the desired code
code, err := refactor.Apply(desiredCode)
if err != nil {
    log.Error(err)
    os.Exit(1)
}

Supported cases

See fixtures

Under the hood

  1. both input and output patterns are converted to go AST nodes
  2. both input and output nodes converted to bblfsh uast.Nodes
  3. define mapping of transformation operations from input to output node
  4. apply transformation mapping to the desired code: traverse over the uast.Nodes tree and transform matching nodes
  5. convert transformed tree back to golang AST
  6. convert golang AST to string

Roadmap

  • currently library copy-pastes a part fo the bblfsh/go-driver because of the dependency issue, fix this part
  • support functions refactor
  • handle cases with cascade ifs, switches and tail recursions
  • during the transformations we are forced to drop nodes positions, need to investigate the possibilities of preserving/reconstructing them(probably using DST nodes could help, related issue dave/dst#38)

About

Advanced utility for golang refactor based on DSL transformations.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages