typeconv

package module
v0.0.0-...-7074a4f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 9, 2017 License: MIT Imports: 6 Imported by: 0

README ΒΆ

go-typeconv - Bring implicit type conversion into Go in a explicit way

Build Status Go Report Card Coverage LICENSE

Go doesn't have implicit type conversion.

Unlike in C, in Go assignment between items of different type requires an explicit conversion. -- Type conversions https://tour.golang.org/basics/13

FAQ: Why does Go not provide implicit numeric conversions? https://golang.org/doc/faq#conversions

I like this design. Explicit is better than implicit. In Go, almost all things are expressed explicitly.

However, sometimes... it's too tedious to fix type coversion errors by hand. If a required type is int64 and got int type, why not converting it automatically? I'm tired of wrapping expressions with int64() or something here and there.

Here comes gotypeconv! gotypeconv takes source code, detects the type conversion errors and fixes them automatically by rewriting AST.

gotypeconv is like gofmt (it actually formats code as well), but it also fixes type conversions errors.

Installation

go get -u github.com/haya14busa/go-typeconv/cmd/gotypeconv

Usage example

./testdata/tour.input.go
// https://tour.golang.org/basics/13
package main

import (
	"fmt"
	"math"
)

func main() {
	var x, y int = 3, 4
	var f float64 = math.Sqrt(x*x + y*y)
	var z uint = f
	fmt.Println(x, y, z)
}

Above code has type conversion errors as follow.

$ go build testdata/tour.input.go
testdata/tour.input.go:11: cannot use x * x + y * y (type int) as type float64 in argument to math.Sqrt
testdata/tour.input.go:12: cannot use f (type float64) as type uint in assignment

gotypeconv can fix them automatically!

$ gotypeconv ./testdata/tour.input.go
// https://tour.golang.org/basics/13
package main

import (
        "fmt"
        "math"
)

func main() {
        var x, y int = 3, 4
        var f float64 = math.Sqrt(float64(x*x + y*y))
        var z uint = uint(f)
        fmt.Println(x, y, z)
}

gotypeconv also supports displaying diff (-d flag) and rewriting files in-place (-w flag) same as gofmt.

More example

Go doesn't have overloading. https://golang.org/doc/faq#overloading I like this design too.

However, sometimes... it's inconvenient. For example, when you want max utility function, you may write something like this func max(x int64, ys ...int64) int64. It works, but when you want to calculate max of given ints, you cannot ues this function unless wrapping them with int64().

You also may start to write func max(x int, ys ...int) int, and change type to int64 later. Then, you need to wrap expressions with int64() here and there in this case as well.

Here comes gotypeconv, again!

package main

import "fmt"

func main() {
	var (
		x int     = 1
		y int64   = 14
		z float64 = -1.4
	)

	var ans int = max(x, x+y, z)
	fmt.Println(ans)
}

func max(x int64, ys ...int64) int64 {
	for _, y := range ys {
		if y > x {
			x = y
		}
	}
	return x
}

Above code can be fixed gotypeconv. ($ gotypeconv -d testdata/max.input.go)

@@ -9,7 +9,7 @@
                z float64 = -1.4
        )

-       var ans int = max(x, x+y, z)
+       var ans int = int(max(int64(x), int64(x)+y, int64(z)))
        fmt.Println(ans)
 }

(I miss generics in this case... but gotypeconv can also solve the problem!)

Hou to Use in Vim

Use https://github.com/haya14busa/vim-gofmt with following sample config.

let g:gofmt_formatters = [
\   { 'cmd': 'gofmt', 'args': ['-s', '-w'] },
\   { 'cmd': 'goimports', 'args': ['-w'] },
\   { 'cmd': 'gotypeconv', 'args': ['-w'] },
\ ]

🐦 Author

haya14busa (https://github.com/haya14busa)

Documentation ΒΆ

Overview ΒΆ

Package typeconv provides missing implicit type conversion in Go by rewriting AST.

Index ΒΆ

Constants ΒΆ

View Source
const (
	// cannot use x (variable of type int) as uint value in variable declaration
	TypeErrVarDecl typErr = iota

	// cannot use x (variable of type int) as float64 value in argument to funcarg
	TypeErrFuncArg

	// cannot use y (variable of type int) as float64 value in assignment
	TypeErrAssign

	// invalid operation: mismatched types int and float64
	TypeErrMismatched

	// cannot use x (variable of type int) as float64 value in return statement
	TypeErrReturn
)

Variables ΒΆ

View Source
var DefaultRule = &Rule{}

DefaultRule holds default type conversion rules whose conversion are safe.

Functions ΒΆ

func Load ΒΆ

func Load(conf loader.Config, args []string) (*loader.Program, []types.Error, error)

Load creates the initial packages specified by conf along with slice of types.Error.

func RewriteProgam ΒΆ

func RewriteProgam(prog *loader.Program, typeErrs []types.Error) error

RewriteProgam rewrites program AST to fix type conversion errors.

Types ΒΆ

type ErrAssign ΒΆ

type ErrAssign struct {
	LeftType  string
	RightType string
}

ErrAssign represents type error at (re) assignments.

type ErrFuncArg ΒΆ

ErrFuncArg represents type error at function arguments.

type ErrMismatched ΒΆ

type ErrMismatched struct {
	LeftType  string
	RightType string
}

ErrMismatched represents mismatched type error.

type ErrReturn ΒΆ

type ErrReturn struct {
	WantType string
	GotType  string
}

ErrReturn represents type error at return statement.

type ErrVarDecl ΒΆ

type ErrVarDecl struct {
	NameType  string
	ValueType string
}

ErrVarDecl represents type error of variable declaration.

Example:

var x, y int = 3, 4
var _ float64 = x*x + y*y
var _ uint = x
var _ uint = int(1)
var _ uint = int(1) + int(1)

Error:

cannot use x * x + y * y (value of type int) as float64 value in variable declaration
cannot use x (variable of type int) as uint value in variable declaration
cannot use int(1) (constant 1 of type int) as uint value in variable declaration
cannot use int(1) + int(1) (constant 2 of type int) as uint value in variable declaration

type Rule ΒΆ

type Rule struct {
	// contains filtered or unexported fields
}

Rule represents type conversion rule.

from -> to -> priority

func (*Rule) Add ΒΆ

func (r *Rule) Add(from, to string)

Add adds type conversion rule.

func (*Rule) ConvertibleTo ΒΆ

func (r *Rule) ConvertibleTo(from, to string) (priority int, ok bool)

ConvertibleTo reports whether a "from" type is convertible to a "to" type.

type TypeError ΒΆ

type TypeError interface {
	// contains filtered or unexported methods
}

TypeError represents type error.

func NewTypeErr ΒΆ

func NewTypeErr(err types.Error) TypeError

NewTypeErr creates TypeError from types.Error.

Directories ΒΆ

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL