func updateSingleLineFunc(
	fset *token.FileSet, up funcUpdate, code string, text string, writer *bytes.Buffer) (cursor int) {
	lbraceOffset := fset.Position(up.fn.Body.Lbrace).Offset
	rbraceOffset := fset.Position(up.fn.Body.Rbrace).Offset
	if len(code) > 0 {
		writer.WriteRune('\n')
		writer.WriteString(code)
		writer.WriteString("\n\n")
		writer.WriteRune('\t')
		fstStmtOffset := fset.Position(up.contractInBody.NextNodePos).Offset
		writer.WriteString(strings.TrimRight(text[fstStmtOffset:rbraceOffset], "\t "))
		writer.WriteString("\n}")
	} else {
		writer.WriteString(text[lbraceOffset+1 : rbraceOffset+1])
	}
	cursor = rbraceOffset + 1
	return
}
updateSingleLineFunc updates the function whose body is a single line of statements separated by ';'.
cursor points just after the right brace of the function definition.
package gocontracts
import (
	"bytes"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"text/template"
	"github.com/Parquery/gocontracts/parsebody"
	"github.com/Parquery/gocontracts/parsecomment"
	"github.com/Parquery/gocontracts/parsecomment/parsecond"
)
type funcUpdate struct {
	contractInDoc  parsecomment.Contract
	fn             *ast.FuncDecl
	contractInBody parsebody.Contract
}
func violationMsg(c parsecond.Condition) string {
	parts := make([]string, 0, 6)
	parts = append(parts, "Violated: ")
	if len(c.Label) > 0 {
		parts = append(parts, fmt.Sprintf("%s: ", c.Label))
	}
	if len(c.InitStr) > 0 {
		parts = append(parts, fmt.Sprintf("%s; ", c.InitStr))
	}
	parts = append(parts, c.CondStr)
	msg := strings.Join(parts, "")
	return strconv.Quote(msg)
}
func negateNot(condStr string, unary *ast.UnaryExpr) string {
	if unary.Op != token.NOT {
		panic(fmt.Sprintf(
			"Expected NOT operator in the unary expression, but got: %d",
			unary.Op))
	}
	parenExpr, isParenExpr := unary.X.(*ast.ParenExpr)
	if !isParenExpr {
		s := unary.X.Pos() - 1
		e := unary.X.End() - 1
		return strings.Trim(condStr[s:e], " \t")
	}
	s := parenExpr.X.Pos() - 1
	e := parenExpr.X.End() - 1
	return strings.Trim(condStr[s:e], " \t")
}
func notCondStr(c parsecond.Condition) string {
	switch v := c.Cond.(type) {
	case *ast.UnaryExpr:
		if v.Op == token.NOT {
			return negateNot(c.CondStr, v)
		}
		return fmt.Sprintf("!(%s)", strings.Trim(c.CondStr, " \t"))
	case *ast.ParenExpr:
		return fmt.Sprintf("!%s", strings.Trim(c.CondStr, " \t"))
	case *ast.Ident:
		return fmt.Sprintf("!%s", strings.Trim(c.CondStr, " \t"))
	}
	return fmt.Sprintf("!(%s)", strings.Trim(c.CondStr, " \t"))
}
func conditionToCode(c parsecond.Condition) string {
	if c.InitStr == "" {
		return notCondStr(c)
	}
	return fmt.Sprintf("%s; %s", c.InitStr, notCondStr(c))
}
var tplPre = template.Must(
	template.New("preconditions").Funcs(
		template.FuncMap{
			"violationMsg":    violationMsg,
			"conditionToCode": conditionToCode,
		}).Parse(
		`{{$l := len .Pres }}{{ if eq $l 1 }}{{ $c := index .Pres 0 }}	 
	if {{ conditionToCode $c }} {
		panic({{ violationMsg $c }})
	}
{{- else }}	 
	switch { {{- range .Pres }}
	case {{ conditionToCode . }}:
		panic({{ violationMsg . }})
{{- end }}
	default:
	}
{{- end }}`))
var tplPost = template.Must(
	template.New("postconditions").Funcs(
		template.FuncMap{
			"violationMsg":    violationMsg,
			"conditionToCode": conditionToCode,
		}).Parse(
		`{{$l := len .Posts }}{{ if eq $l 1 }}{{ $c := index .Posts 0 }}	 
	defer func() {
		if {{ conditionToCode $c }} {
			panic({{ violationMsg $c }})
		}
	}()
{{- else }}	 
	defer func() {
		switch { {{- range .Posts }}
		case {{ conditionToCode . }}:
			panic({{ violationMsg . }})
		{{- end }}
		default:
		}
	}()
{{- end }}`))
func generateCode(contract parsecomment.Contract) (code string, err error) {
	defer func() {
		if strings.HasSuffix(code, "\n") {
			panic("Violated: strings.HasSuffix(code, \"\\n\")")
		}
	}()
	blocks := []string{}
	if len(contract.Pres) > 0 {
		var buf bytes.Buffer
		err = tplPre.Execute(&buf, contract)
		if err != nil {
			return
		}
		blocks = append(blocks, buf.String())
	}
	if len(contract.Preamble) > 0 {
		var buf bytes.Buffer
		buf.WriteString("\t// Preamble starts.\n")
		lines := strings.Split(contract.Preamble, "\n")
		for _, line := range lines {
			buf.WriteString("\t")
			buf.WriteString(line)
			buf.WriteString("\n")
		}
		buf.WriteString("\t// Preamble ends.")
		blocks = append(blocks, buf.String())
	}
	if len(contract.Posts) > 0 {
		var buf bytes.Buffer
		err = tplPost.Execute(&buf, contract)
		if err != nil {
			return
		}
		blocks = append(blocks, buf.String())
	}
	code = strings.Join(blocks, "\n\n")
	return
}
func updateEmptyFunc(fset *token.FileSet, up funcUpdate, code string, writer *bytes.Buffer) (cursor int) {
	cursor = fset.Position(up.fn.Body.Rbrace).Offset  
	if len(code) > 0 {
		writer.WriteRune('\n')
		writer.WriteString(code)
		writer.WriteRune('\n')
	}
	return
}