Beispiel #1
0
func makeCallExpr(name string, params *st.SymbolTable, pointerSymbols map[st.Symbol]int, pos token.Pos, recvSym *st.VariableSymbol, pack *st.Package, filename string) (*ast.CallExpr, int) {
	var Fun ast.Expr
	if recvSym != nil {
		x := ast.NewIdent(recvSym.Name())
		x.NamePos = pos
		Fun = &ast.SelectorExpr{x, ast.NewIdent(name)}
	} else {
		x := ast.NewIdent(name)
		x.NamePos = pos
		Fun = x
	}
	l, _ := utils.GetNodeLength(Fun)
	l += 2

	args, i := make([]ast.Expr, params.Count()), 0
	params.ForEachNoLock(func(sym st.Symbol) {
		args[i] = sym.ToAstExpr(pack, filename)
		if depth, ok := pointerSymbols[sym]; ok {
			for depth > 0 {
				args[i] = &ast.UnaryExpr{token.NoPos, token.AND, args[i]}
				depth--
			}
		}
		ll, _ := utils.GetNodeLength(args[i])
		l += ll + 2
		i++
	})
	l -= 2
	return &ast.CallExpr{Fun, token.NoPos, args, token.NoPos, pos + token.Pos(l-1)}, l
}
Beispiel #2
0
func (vis *destinationVisitor) Visit(node ast.Node) ast.Visitor {
	if node == nil {
		return nil
	}
	switch t := node.(type) {
	case *ast.SelectorExpr:
		ast.Walk(vis, t.X)
		return nil
	case *ast.Ident:
		newExpr := <-vis.Chan
		if newExpr != nil {
			printerUtil.FixPositions(0, int(t.Pos()-newExpr.Pos()), newExpr, true)
			replaceExpr(vis.FileSet.Position(t.Pos()), vis.FileSet.Position(t.End()), newExpr, vis.FileSet, vis.rootNode)
			le, _ := utils.GetNodeLength(newExpr)
			mod := le - int(t.End()-t.Pos())
			for _, stmt := range vis.destList {
				printerUtil.FixPositionsExcept(t.Pos(), mod, stmt, true, map[ast.Node]bool{newExpr: true})
			}
			for i, _ := range vis.nodeLines {
				if vis.nodeLines[i] > vis.TokFile.Offset(t.Pos()) {
					vis.nodeLines[i] += mod
				}
			}
		}
		return nil
	}
	return vis
}
Beispiel #3
0
func extractInterface(programTree *program.Program, filename string, line int, column int, interfaceName string) (bool, *errors.GoRefactorError) {

	if ok, err := CheckExtractInterfaceParameters(filename, line, column, interfaceName); !ok {
		return false, err
	}

	pack, file := programTree.FindPackageAndFileByFilename(filename)
	if pack == nil {
		return false, errors.ArgumentError("filename", "Program packages don't contain file '"+filename+"'")
	}
	fset := pack.FileSet
	mod := 20000
	fset, file = printerUtil.ReparseFile(file, filename, mod, programTree.IdentMap)
	tokFile := printerUtil.GetFileFromFileSet(fset, filename)
	lines := printerUtil.GetLines(tokFile)
	tokFile.SetLines(lines[:len(lines)-(mod)])

	if _, ok := pack.Symbols.LookUp(interfaceName, filename); ok {
		return false, errors.IdentifierAlreadyExistsError(interfaceName)
	}

	field, nameNum, fdecl, ok := getSelectedArgument(file, token.Position{filename, 0, line, column}, fset)
	if !ok {
		return false, &errors.GoRefactorError{ErrorType: "extract interface error", Message: "couldn't find function argument to extract interface"}
	}
	if field.Names == nil {
		return false, &errors.GoRefactorError{ErrorType: "extract interface error", Message: "argument has no name, so empty interface"}
	}

	varS, ok := programTree.IdentMap.GetSymbol(field.Names[nameNum]).(*st.VariableSymbol)
	if !ok {
		panic("symbol supposed to be a variable, but it's not")
	}

	meths, errs := getUsedMethods(programTree, fset, fdecl, varS)
	if len(errs) > 0 {
		println("some errors don't allow to extract interface:")
		for e, _ := range errs {
			println(e.String())
		}
		return false, &errors.GoRefactorError{ErrorType: "extract interface error", Message: "some errors occured, stopped extracting"}
	}
	methList, i := make([]*ast.Field, len(meths)), 0

	for m, _ := range meths {
		methList[i] = &ast.Field{nil, []*ast.Ident{ast.NewIdent(m.Name())}, m.FunctionType.ToAstExpr(pack, filename), nil, nil}
		i++
	}
	interfaceMethods := &ast.FieldList{token.NoPos, methList, token.NoPos}
	interfaceType := &ast.InterfaceType{token.NoPos, interfaceMethods, false}
	interfaceDecl := &ast.TypeSpec{nil, ast.NewIdent(interfaceName), interfaceType, nil}
	genDecl := &ast.GenDecl{nil, token.NoPos, token.TYPE, token.NoPos, []ast.Spec{interfaceDecl}, token.NoPos}

	fieldNum := 0
	for i := 0; i < len(fdecl.Type.Params.List); i++ {
		if field == fdecl.Type.Params.List[i] {
			fieldNum = i
			break
		}
	}

	oldFTypeLen := int(fdecl.Type.End() - fdecl.Type.Pos())

	var lField, mField, rField *ast.Field
	mField = &ast.Field{nil, []*ast.Ident{field.Names[nameNum]}, ast.NewIdent(interfaceName), nil, nil}
	if nameNum > 0 {
		lField = &ast.Field{nil, field.Names[:nameNum], field.Type, nil, nil}
	}
	if nameNum < len(field.Names)-1 {
		rField = &ast.Field{nil, field.Names[(nameNum + 1):], field.Type, nil, nil}
	}
	newList := make([]*ast.Field, fieldNum)
	copy(newList, fdecl.Type.Params.List[:fieldNum])

	if lField != nil {
		newList = append(newList, lField)
	}
	newList = append(newList, mField)
	if rField != nil {
		newList = append(newList, rField)
	}
	newList = append(newList, fdecl.Type.Params.List[(fieldNum+1):]...)
	fdecl.Type.Params.List = newList

	newFTypeLen, _ := utils.GetNodeLength(fdecl.Type)
	newFTypeLen += len(fdecl.Name.Name) + 1

	fmt.Printf("old %d new %d\n", oldFTypeLen, newFTypeLen)
	allMod := newFTypeLen - oldFTypeLen
	if allMod != 0 {
		printerUtil.FixPositions(fdecl.Type.End(), allMod, file, true)

		lines = printerUtil.GetLines(tokFile)
		fmt.Printf("before last (mod = %d) : %v\n", allMod, lines)
		for i, offset := range lines {
			if offset > tokFile.Offset(fdecl.Type.Pos()) {
				for j := i; j < len(lines); j++ {
					lines[j] += allMod
				}
				break
			}
		}
		fmt.Printf("after last (mod = %d) : %v\n", allMod, lines)
		if !tokFile.SetLines(lines) {
			panic("couldn't set lines for file " + tokFile.Name())
		}
	}

	file.Decls = append(file.Decls, genDecl)
	programTree.SaveFileExplicit(filename, fset, file)
	return true, nil

}