JavaCallListener.go 12.1 KB
Newer Older
P
Phodal HUANG 已提交
1
package call
P
Phodal HUANG 已提交
2 3

import (
P
Phodal Huang 已提交
4 5
	"coca/src/adapter/models"
	"coca/src/language/java"
P
Phodal HUANG 已提交
6
	"github.com/antlr/antlr4/runtime/Go/antlr"
P
Phodal HUANG 已提交
7 8
	"reflect"
	"strings"
P
Phodal HUANG 已提交
9 10 11
)

var imports []string
P
Phodal HUANG 已提交
12
var clzs []string
P
Phodal HUANG 已提交
13 14
var currentPkg string
var currentClz string
P
Phodal Huang 已提交
15 16 17
var fields []models.JAppField
var methods []models.JMethod
var methodCalls []models.JMethodCall
P
Phodal HUANG 已提交
18
var currentType string
P
Phodal HUANG 已提交
19

P
Phodal Huang 已提交
20
var mapFields = make(map[string]string)
P
Phodal HUANG 已提交
21 22
var localVars = make(map[string]string)
var formalParameters = make(map[string]string)
P
Phodal Huang 已提交
23
var currentClzExtends = ""
P
Phodal Huang 已提交
24
var currentMethod models.JMethod
P
Phodal Huang 已提交
25
var methodMap = make(map[string]models.JMethod)
P
Phodal HUANG 已提交
26

P
Phodal Huang 已提交
27
var methodQueue []models.JMethod
28
var identNodes []models.JsonIdentifier
P
Phodal Huang 已提交
29

30
func NewJavaCallListener(nodes []models.JsonIdentifier) *JavaCallListener {
P
Phodal HUANG 已提交
31 32
	currentClz = ""
	currentPkg = ""
P
Phodal Huang 已提交
33
	currentMethod = models.NewJMethod()
34
	identNodes = nodes
P
Phodal Huang 已提交
35

P
Phodal Huang 已提交
36 37
	methodMap = make(map[string]models.JMethod)

P
Phodal HUANG 已提交
38
	methods = nil
P
Phodal HUANG 已提交
39
	methodCalls = nil
P
Phodal Huang 已提交
40
	fields = nil
P
Phodal HUANG 已提交
41 42 43
	return &JavaCallListener{}
}

P
Phodal HUANG 已提交
44
type JavaCallListener struct {
P
Phodal Huang 已提交
45
	parser.BaseJavaParserListener
P
Phodal HUANG 已提交
46 47
}

P
Phodal Huang 已提交
48
func (s *JavaCallListener) getNodeInfo() *models.JClassNode {
P
Phodal Huang 已提交
49 50 51 52 53
	var methodsArray []models.JMethod
	for _, value := range methodMap {
		methodsArray = append(methodsArray, value)
	}
	return &models.JClassNode{currentPkg, currentClz, currentType, "", fields, methodsArray, methodCalls}
P
Phodal HUANG 已提交
54 55
}

P
Phodal Huang 已提交
56
func (s *JavaCallListener) EnterPackageDeclaration(ctx *parser.PackageDeclarationContext) {
P
Phodal HUANG 已提交
57 58 59
	currentPkg = ctx.QualifiedName().GetText()
}

P
Phodal Huang 已提交
60
func (s *JavaCallListener) EnterImportDeclaration(ctx *parser.ImportDeclarationContext) {
P
Phodal HUANG 已提交
61 62 63 64
	importText := ctx.QualifiedName().GetText()
	imports = append(imports, importText)
}

P
Phodal Huang 已提交
65
func (s *JavaCallListener) EnterClassDeclaration(ctx *parser.ClassDeclarationContext) {
P
Phodal HUANG 已提交
66
	currentType = "Class"
P
Phodal Huang 已提交
67 68 69
	if ctx.IDENTIFIER() != nil {
		currentClz = ctx.IDENTIFIER().GetText()
	}
P
Phodal Huang 已提交
70 71 72 73

	if ctx.EXTENDS() != nil {
		currentClzExtends = ctx.TypeType().GetText()
	}
P
Phodal HUANG 已提交
74 75
}

P
Phodal Huang 已提交
76
func (s *JavaCallListener) EnterInterfaceDeclaration(ctx *parser.InterfaceDeclarationContext) {
P
Phodal HUANG 已提交
77
	currentType = "Interface"
P
Phodal HUANG 已提交
78 79 80
	currentClz = ctx.IDENTIFIER().GetText()
}

P
Phodal Huang 已提交
81
func (s *JavaCallListener) EnterInterfaceMethodDeclaration(ctx *parser.InterfaceMethodDeclarationContext) {
P
Phodal HUANG 已提交
82
	startLine := ctx.GetStart().GetLine()
P
Phodal HUANG 已提交
83
	startLinePosition := ctx.IDENTIFIER().GetSymbol().GetColumn()
P
Phodal HUANG 已提交
84 85
	stopLine := ctx.GetStop().GetLine()
	name := ctx.IDENTIFIER().GetText()
P
Phodal HUANG 已提交
86
	stopLinePosition := startLinePosition + len(name)
P
Phodal HUANG 已提交
87

P
Phodal HUANG 已提交
88
	typeType := ctx.TypeTypeOrVoid().GetText()
P
Phodal HUANG 已提交
89

90
	method := &models.JMethod{name, typeType, startLine, startLinePosition, stopLine, stopLinePosition, nil, nil, false}
P
Phodal HUANG 已提交
91
	methods = append(methods, *method)
P
Phodal HUANG 已提交
92 93
}

P
Phodal Huang 已提交
94
func (s *JavaCallListener) EnterFormalParameter(ctx *parser.FormalParameterContext) {
P
Phodal HUANG 已提交
95 96 97
	formalParameters[ctx.VariableDeclaratorId().GetText()] = ctx.TypeType().GetText()
}

P
Phodal Huang 已提交
98
func (s *JavaCallListener) EnterFieldDeclaration(ctx *parser.FieldDeclarationContext) {
P
Phodal Huang 已提交
99 100
	decelerators := ctx.VariableDeclarators()
	typeType := decelerators.GetParent().GetChild(0).(antlr.ParseTree).GetText()
P
Phodal Huang 已提交
101 102
	for _, declarator := range decelerators.(*parser.VariableDeclaratorsContext).AllVariableDeclarator() {
		value := declarator.(*parser.VariableDeclaratorContext).VariableDeclaratorId().(*parser.VariableDeclaratorIdContext).IDENTIFIER().GetText()
P
Phodal Huang 已提交
103
		mapFields[value] = typeType
P
Phodal Huang 已提交
104
		fields = append(fields, *&models.JAppField{Type: typeType, Value: value})
P
Phodal Huang 已提交
105
	}
P
Phodal HUANG 已提交
106 107
}

P
Phodal Huang 已提交
108
func (s *JavaCallListener) EnterLocalVariableDeclaration(ctx *parser.LocalVariableDeclarationContext) {
P
Phodal HUANG 已提交
109
	typ := ctx.GetChild(0).(antlr.ParseTree).GetText()
P
Phodal Huang 已提交
110
	if ctx.GetChild(1) != nil {
P
Phodal Huang 已提交
111
		if ctx.GetChild(1).GetChild(0) != nil && ctx.GetChild(1).GetChild(0).GetChild(0) != nil {
P
Phodal Huang 已提交
112 113 114 115 116

			variableName := ctx.GetChild(1).GetChild(0).GetChild(0).(antlr.ParseTree).GetText()
			localVars[variableName] = typ
		}
	}
P
Phodal HUANG 已提交
117 118
}

P
Phodal Huang 已提交
119
func (s *JavaCallListener) EnterMethodDeclaration(ctx *parser.MethodDeclarationContext) {
P
Phodal HUANG 已提交
120
	startLine := ctx.GetStart().GetLine()
P
Phodal HUANG 已提交
121
	startLinePosition := ctx.IDENTIFIER().GetSymbol().GetColumn()
P
Phodal HUANG 已提交
122 123
	stopLine := ctx.GetStop().GetLine()
	name := ctx.IDENTIFIER().GetText()
P
Phodal HUANG 已提交
124
	stopLinePosition := startLinePosition + len(name)
P
Phodal HUANG 已提交
125

P
Phodal HUANG 已提交
126
	typeType := ctx.TypeTypeOrVoid().GetText()
P
Phodal HUANG 已提交
127

128
	method := &models.JMethod{name, typeType, startLine, startLinePosition, stopLine, stopLinePosition, nil, nil, false}
P
Phodal Huang 已提交
129 130

	if ctx.FormalParameters() != nil {
P
Phodal Huang 已提交
131
		if ctx.FormalParameters().GetChild(0) == nil || ctx.FormalParameters().GetText() == "()" || ctx.FormalParameters().GetChild(1) == nil {
P
Phodal Huang 已提交
132
			currentMethod = *method
P
Phodal Huang 已提交
133 134 135
			return
		}

P
Phodal Huang 已提交
136 137
		var methodParams []models.JParameter = nil
		parameterList := ctx.FormalParameters().GetChild(1).(*parser.FormalParameterListContext)
P
Phodal Huang 已提交
138 139
		formalParameter := parameterList.AllFormalParameter()
		for _, param := range formalParameter {
P
Phodal Huang 已提交
140
			paramContext := param.(*parser.FormalParameterContext)
P
Phodal Huang 已提交
141
			paramType := paramContext.TypeType().GetText()
P
Phodal Huang 已提交
142
			paramValue := paramContext.VariableDeclaratorId().(*parser.VariableDeclaratorIdContext).IDENTIFIER().GetText()
P
Phodal Huang 已提交
143 144

			localVars[paramValue] = paramType
P
Phodal Huang 已提交
145
			methodParams = append(methodParams, *&models.JParameter{paramType, paramValue})
P
Phodal Huang 已提交
146
		}
P
Phodal Huang 已提交
147

P
Phodal Huang 已提交
148
		method.Parameters = methodParams
P
Phodal Huang 已提交
149
	}
P
Phodal Huang 已提交
150

P
Phodal Huang 已提交
151
	methodQueue = append(methodQueue, *method)
P
Phodal Huang 已提交
152
	currentMethod = *method
P
Phodal Huang 已提交
153
	methodMap[getMethodMapName(*method)] = *method
P
Phodal Huang 已提交
154 155
}

P
Phodal Huang 已提交
156
func (s *JavaCallListener) ExitMethodDeclaration(ctx *parser.MethodDeclarationContext) {
P
Phodal Huang 已提交
157 158 159
	if len(methodQueue) > 1 {
		methodQueue = methodQueue[0 : len(methodQueue)-1]
	}
P
Phodal Huang 已提交
160 161 162
	currentMethod = models.NewJMethod()
}

P
Phodal Huang 已提交
163
func getMethodMapName(method models.JMethod) string {
P
Phodal Huang 已提交
164
	name := method.Name
P
Phodal Huang 已提交
165
	if name == "" && len(methodQueue) > 1 {
P
Phodal Huang 已提交
166 167 168
		name = methodQueue[len(methodQueue)-1 ].Name
	}
	return currentPkg + "." + currentClz + "." + name
P
Phodal HUANG 已提交
169 170
}

P
Phodal Huang 已提交
171
func (s *JavaCallListener) EnterCreator(ctx *parser.CreatorContext) {
P
Phodal Huang 已提交
172
	variableName := ctx.GetParent().GetParent().GetChild(0).(antlr.ParseTree).GetText()
P
Phodal Huang 已提交
173 174 175 176 177 178 179
	createdName := ctx.CreatedName().GetText()
	localVars[variableName] = createdName

	if currentMethod.Name == "" {
		return
	}

P
Phodal Huang 已提交
180 181 182
	defer func() {
		buildCreatedCall(createdName, ctx)
	}()
P
Phodal Huang 已提交
183 184
}

P
Phodal Huang 已提交
185
func buildCreatedCall(createdName string, ctx *parser.CreatorContext) {
P
Phodal Huang 已提交
186 187
	method := methodMap[getMethodMapName(currentMethod)]
	fullType := warpTargetFullType(createdName)
P
Phodal Huang 已提交
188 189 190 191 192 193

	startLine := ctx.GetStart().GetLine()
	startLinePosition := ctx.GetStart().GetColumn()
	stopLine := ctx.GetStop().GetLine()
	stopLinePosition := ctx.GetStop().GetColumn()

P
Phodal Huang 已提交
194 195
	jMethodCall := &models.JMethodCall{
		Package:           removeTarget(fullType),
P
Phodal Huang 已提交
196
		Type:              "Creator",
P
Phodal Huang 已提交
197 198
		Class:             createdName,
		MethodName:        "",
P
Phodal Huang 已提交
199 200 201 202
		StartLine:         startLine,
		StartLinePosition: startLinePosition,
		StopLine:          stopLine,
		StopLinePosition:  stopLinePosition,
P
Phodal Huang 已提交
203 204 205
	}
	method.MethodCalls = append(method.MethodCalls, *jMethodCall)
	methodMap[getMethodMapName(currentMethod)] = method
P
Phodal Huang 已提交
206
}
P
Phodal Huang 已提交
207

P
Phodal Huang 已提交
208
func (s *JavaCallListener) EnterLocalTypeDeclaration(ctx *parser.LocalTypeDeclarationContext) {
P
Phodal Huang 已提交
209
	// TODO
P
Phodal Huang 已提交
210
}
P
Phodal Huang 已提交
211

P
Phodal Huang 已提交
212
func (s *JavaCallListener) EnterMethodCall(ctx *parser.MethodCallContext) {
P
Phodal HUANG 已提交
213 214
	var targetCtx = ctx.GetParent().GetChild(0).(antlr.ParseTree).GetText()
	var targetType = parseTargetType(targetCtx)
P
Phodal HUANG 已提交
215 216 217
	callee := ctx.GetChild(0).(antlr.ParseTree).GetText()

	startLine := ctx.GetStart().GetLine()
P
Phodal HUANG 已提交
218
	startLinePosition := ctx.GetStart().GetColumn()
P
Phodal HUANG 已提交
219
	stopLine := ctx.GetStop().GetLine()
P
Phodal HUANG 已提交
220
	stopLinePosition := startLinePosition + len(callee)
P
Phodal HUANG 已提交
221

P
Phodal Huang 已提交
222
	// TODO: 处理链试调用
P
Phodal Huang 已提交
223
	if strings.Contains(targetType, "(") && strings.Contains(targetType, ")") && strings.Contains(targetType, ".") {
P
Phodal Huang 已提交
224 225 226 227 228 229
		split := strings.Split(targetType, ".")
		sourceTarget := split[0]
		targetType = localVars[sourceTarget]
	}

	fullType := warpTargetFullType(targetType)
P
Phodal Huang 已提交
230 231 232
	if targetType == "super" {
		targetType = currentClzExtends
	}
P
Phodal Huang 已提交
233 234

	var jMethodCall = &models.JMethodCall{}
P
Phodal HUANG 已提交
235
	if fullType != "" {
P
Phodal Huang 已提交
236 237 238 239 240
		if targetType == "" {
			// 处理自调用
			targetType = currentClz
		}

P
Phodal Huang 已提交
241
		jMethodCall = &models.JMethodCall{removeTarget(fullType), "", targetType, callee, startLine, startLinePosition, stopLine, stopLinePosition}
P
Phodal HUANG 已提交
242
	} else {
P
Phodal HUANG 已提交
243 244
		if ctx.GetText() == targetType {
			methodName := ctx.IDENTIFIER().GetText()
P
Phodal Huang 已提交
245 246
			pkg := currentPkg
			clz := currentClz
P
Phodal Huang 已提交
247
			// 处理 static 方法,如 now()
P
Phodal Huang 已提交
248 249 250 251 252 253 254
			for _, imp := range imports {
				if strings.HasSuffix(imp, "."+methodName) {
					pkg = imp
					clz = ""
				}
			}
			jMethodCall = &models.JMethodCall{pkg, "", clz, methodName, startLine, startLinePosition, stopLine, stopLinePosition}
P
Phodal Huang 已提交
255
		} else {
P
Phodal Huang 已提交
256
			methodName := ctx.IDENTIFIER().GetText()
P
Phodal Huang 已提交
257 258
			targetType = buildSpecificTarget(targetType)

P
Phodal Huang 已提交
259 260
			targetType = buildMethodNameForBuilder(ctx, targetType)

P
Phodal Huang 已提交
261
			jMethodCall = &models.JMethodCall{currentPkg, "NEEDFIX", targetType, methodName, startLine, startLinePosition, stopLine, stopLinePosition}
P
Phodal HUANG 已提交
262
		}
P
Phodal HUANG 已提交
263
	}
P
Phodal Huang 已提交
264 265

	methodCalls = append(methodCalls, *jMethodCall)
P
Phodal Huang 已提交
266 267 268 269

	method := methodMap[getMethodMapName(currentMethod)]
	method.MethodCalls = append(method.MethodCalls, *jMethodCall)
	methodMap[getMethodMapName(currentMethod)] = method
P
Phodal HUANG 已提交
270 271
}

P
Phodal Huang 已提交
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
func buildMethodNameForBuilder(ctx *parser.MethodCallContext, targetType string) string {
	// TODO: refactor
	if reflect.TypeOf(ctx.GetParent()).String() == "*parser.ExpressionContext" {
		parentCtx := ctx.GetParent().(*parser.ExpressionContext)
		if reflect.TypeOf(parentCtx.GetParent()).String() == "*parser.VariableInitializerContext" {
			varParent := parentCtx.GetParent().(*parser.VariableInitializerContext).GetParent()
			if reflect.TypeOf(varParent).String() == "*parser.VariableDeclaratorContext" {
				varDeclParent := varParent.(*parser.VariableDeclaratorContext).GetParent()
				if reflect.TypeOf(varDeclParent).String() == "*parser.VariableDeclaratorsContext" {
					parent := varDeclParent.(*parser.VariableDeclaratorsContext).GetParent()
					targetType = parent.(*parser.LocalVariableDeclarationContext).TypeType().GetText()
				}
			}
		}
	}

	return targetType
}

P
Phodal Huang 已提交
291 292 293 294 295 296 297 298 299 300 301 302 303
func buildSpecificTarget(targetType string) string {
	isSelfFieldCall := strings.Contains(targetType, "this.")
	if isSelfFieldCall {
		targetType = strings.ReplaceAll(targetType, "this.", "")
		for _, field := range fields {
			if field.Value == targetType {
				targetType = field.Type
			}
		}
	}
	return targetType
}

P
Phodal Huang 已提交
304
func (s *JavaCallListener) EnterExpression(ctx *parser.ExpressionContext) {
P
Phodal HUANG 已提交
305
	// lambda BlogPO::of
P
Phodal HUANG 已提交
306
	if ctx.COLONCOLON() != nil {
P
Phodal Huang 已提交
307 308 309 310
		if ctx.Expression(0) == nil {
			return
		}

P
Phodal HUANG 已提交
311
		text := ctx.Expression(0).GetText()
P
Phodal HUANG 已提交
312
		methodName := ctx.IDENTIFIER().GetText()
P
Phodal HUANG 已提交
313 314 315 316 317 318 319 320
		targetType := parseTargetType(text)
		fullType := warpTargetFullType(targetType)

		startLine := ctx.GetStart().GetLine()
		startLinePosition := ctx.GetStart().GetColumn()
		stopLine := ctx.GetStop().GetLine()
		stopLinePosition := startLinePosition + len(text)

P
Phodal Huang 已提交
321
		jMethodCall := &models.JMethodCall{removeTarget(fullType), "", targetType, methodName, startLine, startLinePosition, stopLine, stopLinePosition}
P
Phodal HUANG 已提交
322 323 324 325
		methodCalls = append(methodCalls, *jMethodCall)
	}
}

P
Phodal HUANG 已提交
326 327 328 329
func (s *JavaCallListener) appendClasses(classes []string) {
	clzs = classes
}

P
Phodal HUANG 已提交
330 331 332 333 334
func removeTarget(fullType string) string {
	split := strings.Split(fullType, ".")
	return strings.Join(split[:len(split)-1], ".")
}

P
Phodal HUANG 已提交
335 336 337
func parseTargetType(targetCtx string) string {
	targetVar := targetCtx
	targetType := targetVar
P
Phodal HUANG 已提交
338

P
Phodal HUANG 已提交
339 340 341
	//TODO: update this reflect
	typeOf := reflect.TypeOf(targetCtx).String()
	if strings.HasSuffix(typeOf, "MethodCallContext") {
P
Phodal Huang 已提交
342
		targetType = currentClz
P
Phodal HUANG 已提交
343
	} else {
P
Phodal Huang 已提交
344
		fieldType := mapFields[targetVar]
P
Phodal HUANG 已提交
345 346 347 348 349
		formalType := formalParameters[targetVar]
		localVarType := localVars[targetVar]
		if fieldType != "" {
			targetType = fieldType
		} else if formalType != "" {
P
Phodal Huang 已提交
350
			targetType = formalType
P
Phodal HUANG 已提交
351
		} else if localVarType != "" {
P
Phodal Huang 已提交
352
			targetType = localVarType
P
Phodal HUANG 已提交
353 354 355
		}
	}

P
Phodal HUANG 已提交
356
	return targetType
P
Phodal HUANG 已提交
357
}
P
Phodal HUANG 已提交
358 359 360

func warpTargetFullType(targetType string) string {
	if strings.EqualFold(currentClz, targetType) {
P
Phodal HUANG 已提交
361
		return currentPkg + "." + targetType
P
Phodal HUANG 已提交
362
	}
P
Phodal HUANG 已提交
363

P
Phodal Huang 已提交
364
	// TODO: update for array
P
Phodal Huang 已提交
365
	split := strings.Split(targetType, ".")
P
Phodal Huang 已提交
366 367 368
	str := split[0]
	pureTargetType := strings.ReplaceAll(strings.ReplaceAll(str, "[", ""), "]", "")

P
Phodal HUANG 已提交
369 370
	for index := range imports {
		imp := imports[index]
P
Phodal Huang 已提交
371
		if strings.HasSuffix(imp, pureTargetType) {
P
Phodal HUANG 已提交
372 373 374 375
			return imp
		}
	}

P
Phodal HUANG 已提交
376 377
	//maybe the same package
	for _, clz := range clzs {
P
Phodal Huang 已提交
378
		if strings.HasSuffix(clz, "."+pureTargetType) {
P
Phodal HUANG 已提交
379 380 381 382 383
			return clz
		}
	}

	//1. current package, 2. import by *
P
Phodal Huang 已提交
384 385 386 387 388 389 390 391 392
	if pureTargetType == "super" {
		for index := range imports {
			imp := imports[index]
			if strings.HasSuffix(imp, currentClzExtends) {
				return imp
			}
		}
	}

P
Phodal HUANG 已提交
393 394
	return ""
}