forked from skelterjohn/gorf
/
merge.go
123 lines (103 loc) · 2.64 KB
/
merge.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright 2011 John Asmuth. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
//"go/ast"
"code.google.com/p/rog-go/exp/go/ast"
"path/filepath"
)
func MergeCmd(args []string) (err error) {
if len(args) != 2 {
return MakeErr("Usage: gorf [flags] merge <old path> <new path>")
}
oldpath, newpath := filepath.Clean(args[0]), filepath.Clean(args[1])
err = ScanAllForImports(LocalRoot)
if err != nil {
return
}
PreloadImportedBy(oldpath)
defer func() {
if err != nil {
UndoCmd([]string{})
}
}()
if PackageTops[oldpath] == nil {
return MakeErr("Old path %s has no local package", oldpath)
}
if PackageTops[newpath] == nil {
return MakeErr("New path %s has no local package", newpath)
}
oldpkg, newpkg := LocalImporter(oldpath), LocalImporter(newpath)
// check for conflicts
duplicates := false
for name, oldobj := range oldpkg.Scope.Objects {
if oldobj.Decl == nil {
continue
}
if newobj, ok := newpkg.Scope.Objects[name]; ok && newobj.Decl != nil {
duplicates = true
fmt.Printf("Duplicate name %s\n", name)
if oldNode, oldOk := oldobj.Decl.(ast.Node); oldOk {
fmt.Printf(" %s\n", AllSources.Position(oldNode.Pos()))
} else {
fmt.Printf("%T\n", oldobj.Decl)
}
if newNode, newOk := newobj.Decl.(ast.Node); newOk {
fmt.Printf(" %s\n", AllSources.Position(newNode.Pos()))
} else {
fmt.Printf("%T\n", newobj.Decl)
}
}
}
if duplicates {
return MakeErr("Packages in '%s' and '%s' contain duplicate names", oldpath, newpath)
}
//move source files
for fpath := range oldpkg.Files {
_, fname := filepath.Split(fpath)
npath := GetUniqueFilename(newpkg, filepath.Join(newpath, fname))
err = MoveSource(fpath, npath)
if err != nil {
return
}
}
//update imports
for _, ipath := range ImportedBy[QuotePath(oldpath)] {
pkg := LocalImporter(ipath)
for fpath, file := range pkg.Files {
ir := ImportRepath {
OldName : oldpkg.Name,
OldPath : oldpath,
NewPath : newpath,
}
ast.Walk(&ir, file)
if ir.Updated {
err = RewriteSource(fpath, file)
if err != nil {
return
}
}
}
}
return// MakeErr("not implemented yet")
}
type ImportRepath struct {
OldName string
OldPath, NewPath string
Updated bool
}
func (this *ImportRepath) Visit(node ast.Node) ast.Visitor {
if is, ok := node.(*ast.ImportSpec); ok {
if is.Path.Value == QuotePath(this.OldPath) {
is.Path.Value = QuotePath(this.NewPath)
if is.Name == nil {
is.Name = &ast.Ident{ Name : this.OldName }
}
this.Updated = true
return nil
}
}
return this
}