move_class_app.go 3.8 KB
Newer Older
P
Phodal HUANG 已提交
1
package move_class
P
Phodal HUANG 已提交
2 3 4

import (
	"bufio"
5 6
	"fmt"
	"github.com/antlr/antlr4/runtime/Go/antlr"
P
Phodal Huang 已提交
7
	"github.com/phodal/coca/core/adapter/coca_file"
P
Phodal Huang 已提交
8 9
	base2 "github.com/phodal/coca/core/context/refactor/base"
	models2 "github.com/phodal/coca/core/context/refactor/base/models"
P
Phodal Huang 已提交
10
	"io"
P
Phodal HUANG 已提交
11
	"io/ioutil"
P
Phodal HUANG 已提交
12 13 14
	"log"
	"os"
	"path/filepath"
P
Phodal HUANG 已提交
15
	"strings"
P
Phodal HUANG 已提交
16 17 18 19
)

var currentFile string
var moveConfig string
P
Phodal HUANG 已提交
20
var configPath string
P
Phodal HUANG 已提交
21

P
Phodal Huang 已提交
22
var nodes []models2.JMoveStruct
P
Phodal HUANG 已提交
23 24 25 26 27 28

type MoveClassApp struct {
}

func NewMoveClassApp(config string, pPath string) *MoveClassApp {
	moveConfig = config
P
Phodal HUANG 已提交
29
	configPath = pPath
P
Phodal HUANG 已提交
30

P
Phodal HUANG 已提交
31
	nodes = nil
P
Phodal HUANG 已提交
32 33 34
	return &MoveClassApp{}
}

P
Phodal Huang 已提交
35
func (j *MoveClassApp) Analysis() []models2.JMoveStruct {
P
Phodal Huang 已提交
36
	// TODO: 使用 Deps.json 来移动包
P
Phodal Huang 已提交
37
	files := coca_file.GetJavaFiles(configPath)
P
Phodal HUANG 已提交
38 39 40 41 42
	for index := range files {
		file := files[index]

		currentFile, _ = filepath.Abs(file)

P
Phodal Huang 已提交
43
		parser := coca_file.ProcessFile(file)
P
Phodal HUANG 已提交
44 45
		context := parser.CompilationUnit()

P
Phodal Huang 已提交
46 47
		node := models2.NewJFullIdentifier()
		listener := new(base2.JavaRefactorListener)
P
Phodal HUANG 已提交
48 49 50 51
		listener.InitNode(node)

		antlr.NewParseTreeWalker().Walk(listener, context)

P
Phodal Huang 已提交
52
		node = listener.GetNodeInfo()
P
Phodal Huang 已提交
53
		moveStruct := &models2.JMoveStruct{node, currentFile, node.GetImports()}
P
Phodal HUANG 已提交
54
		nodes = append(nodes, *moveStruct)
P
Phodal HUANG 已提交
55 56
	}

P
Phodal Huang 已提交
57
	return nodes
P
Phodal HUANG 已提交
58 59
}

P
Phodal Huang 已提交
60
func (j *MoveClassApp) Refactoring() {
P
Phodal HUANG 已提交
61 62 63 64 65 66 67 68
	file, err := os.Open(moveConfig)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
P
Phodal HUANG 已提交
69 70 71 72 73 74 75 76
		splitStr := strings.Split(scanner.Text(), " -> ")
		if len(splitStr) < 2 {
			return
		}

		originImport := splitStr[0]
		newImport := splitStr[1]

P
Phodal Huang 已提交
77 78
		originFile  := buildJavaPath(configPath, originImport)
		newFile := buildJavaPath(configPath, newImport)
P
Phodal HUANG 已提交
79

P
Phodal Huang 已提交
80 81
		// for travis test
		fmt.Println(originFile, newFile)
P
Phodal HUANG 已提交
82 83
		copyClass(originFile, newFile)

P
Phodal Huang 已提交
84
		updatePackageInfo(originImport, newImport)
P
Phodal HUANG 已提交
85 86 87 88
		updateImportSide(originImport, newImport)
	}
}

P
Phodal Huang 已提交
89
func updatePackageInfo(originImport string, newImport string) {
P
Phodal Huang 已提交
90
	var originNode models2.JMoveStruct
P
Phodal HUANG 已提交
91 92
	for index := range nodes {
		node := nodes[index]
93
		if originImport == node.Pkg+"."+node.Name {
P
Phodal HUANG 已提交
94 95 96 97 98 99 100
			originNode = node
		}
	}

	if originNode.Name == "" {
		return
	}
P
Phodal Huang 已提交
101

P
Phodal Huang 已提交
102
	path := buildJavaPath(configPath, newImport)
P
Phodal HUANG 已提交
103
	split := strings.Split(newImport, ".")
104 105
	pkg := strings.Join(split[:len(split)-1], ".")
	updateFile(path, originNode.GetPkgInfo().StartLine, "package "+pkg+";")
P
Phodal HUANG 已提交
106 107
}

P
Phodal HUANG 已提交
108 109 110
func updateImportSide(originImport string, newImport string) {
	for index := range nodes {
		node := nodes[index]
P
Phodal HUANG 已提交
111 112
		for j := range node.Deps {
			dep := node.Deps[j]
P
Phodal HUANG 已提交
113
			if dep.Name == originImport {
P
Phodal HUANG 已提交
114
				updateFile(node.Path, dep.StartLine, "import "+newImport+";")
P
Phodal HUANG 已提交
115 116
			}
		}
P
Phodal HUANG 已提交
117 118 119
	}
}

P
Phodal HUANG 已提交
120 121 122 123
func updateFile(path string, lineNum int, newImp string) {
	input, err := ioutil.ReadFile(path)
	if err != nil {
		log.Fatalln(err)
P
Phodal HUANG 已提交
124 125
	}

P
Phodal HUANG 已提交
126 127 128 129
	lines := strings.Split(string(input), "\n")

	for i := range lines {
		if i == lineNum {
130
			lines[i-1] = newImp
P
Phodal HUANG 已提交
131 132 133 134 135 136 137 138
		}
	}
	output := strings.Join(lines, "\n")
	err = ioutil.WriteFile(path, []byte(output), 0644)
	if err != nil {
		log.Fatalln(err)
	}
}
P
Phodal HUANG 已提交
139

P
Phodal HUANG 已提交
140
func copyClass(originFile string, newFile string) {
P
Phodal Huang 已提交
141
	_, err := CopyFile(originFile, newFile)
P
Phodal HUANG 已提交
142
	if err != nil {
P
Phodal Huang 已提交
143
		log.Fatalln(err)
P
Phodal HUANG 已提交
144 145 146
	}
}

P
Phodal Huang 已提交
147 148 149
func buildJavaPath(configPath string, importStr string) string {
	if !strings.HasSuffix(configPath, "/") {
		configPath = configPath + "/"
150
	}
P
Phodal Huang 已提交
151 152
	path := configPath + strings.ReplaceAll(importStr, ".", "/") + ".java"
	return filepath.FromSlash(path)
P
Phodal HUANG 已提交
153
}
P
Phodal Huang 已提交
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178

func CopyFile(src, dst string) (int64, error) {
	sourceFileStat, err := os.Stat(src)
	if err != nil {
		return 0, err
	}

	if !sourceFileStat.Mode().IsRegular() {
		return 0, fmt.Errorf("%s is not a regular file", src)
	}

	source, err := os.Open(src)
	if err != nil {
		return 0, err
	}
	defer source.Close()

	destination, err := os.Create(dst)
	if err != nil {
		return 0, err
	}
	defer destination.Close()
	nBytes, err := io.Copy(destination, source)
	return nBytes, err
}