From 399d4e000b886441a1263e1b97f881f91b1ccdc4 Mon Sep 17 00:00:00 2001 From: Phodal Huang Date: Mon, 4 Dec 2023 21:48:32 +0800 Subject: [PATCH] feat: import badsmell from coca --- .../eval/picker/bs/BadSmellGraphCall.kt | 46 ++++ .../eval/picker/bs/BadsmellAnalyser.kt | 216 ++++++++++++++++- .../org/unimesh/eval/picker/bs/BsAnalyser.kt | 47 ++++ .../src/test/resources/bs/ComplexIf.java | 70 ++++++ .../src/test/resources/bs/DataClass.java | 22 ++ .../src/test/resources/bs/LargeClass.java | 24 ++ .../src/test/resources/bs/LazyClass.java | 3 + .../src/test/resources/bs/LongMethod.java | 227 ++++++++++++++++++ .../src/test/resources/bs/LongParameter.java | 7 + .../src/test/resources/bs/MultipleIf.java | 24 ++ .../resources/bs/graphcall/GraphCallA.java | 12 + .../resources/bs/graphcall/GraphCallB.java | 9 + .../resources/bs/graphcall/GraphCallC.java | 8 + .../bs/interface/BlogRepository.java | 19 ++ 14 files changed, 732 insertions(+), 2 deletions(-) create mode 100644 unit-picker/src/main/kotlin/org/unimesh/eval/picker/bs/BadSmellGraphCall.kt create mode 100644 unit-picker/src/test/kotlin/org/unimesh/eval/picker/bs/BsAnalyser.kt create mode 100644 unit-picker/src/test/resources/bs/ComplexIf.java create mode 100644 unit-picker/src/test/resources/bs/DataClass.java create mode 100644 unit-picker/src/test/resources/bs/LargeClass.java create mode 100644 unit-picker/src/test/resources/bs/LazyClass.java create mode 100644 unit-picker/src/test/resources/bs/LongMethod.java create mode 100644 unit-picker/src/test/resources/bs/LongParameter.java create mode 100644 unit-picker/src/test/resources/bs/MultipleIf.java create mode 100644 unit-picker/src/test/resources/bs/graphcall/GraphCallA.java create mode 100644 unit-picker/src/test/resources/bs/graphcall/GraphCallB.java create mode 100644 unit-picker/src/test/resources/bs/graphcall/GraphCallC.java create mode 100644 unit-picker/src/test/resources/bs/interface/BlogRepository.java diff --git a/unit-picker/src/main/kotlin/org/unimesh/eval/picker/bs/BadSmellGraphCall.kt b/unit-picker/src/main/kotlin/org/unimesh/eval/picker/bs/BadSmellGraphCall.kt new file mode 100644 index 00000000..1e978b7c --- /dev/null +++ b/unit-picker/src/main/kotlin/org/unimesh/eval/picker/bs/BadSmellGraphCall.kt @@ -0,0 +1,46 @@ +package org.unimesh.eval.picker.bs + +class BadSmellGraphCall { + companion object { + var totalPath: MutableList = mutableListOf() + } + + fun analysisGraphCallPath(nodes: Map>): List { + for (k in nodes.keys) { + getConnectedPath(k, nodes) + } + return totalPath + } + + private fun getConnectedPath(startNode: String, nodes: Map>) { + val relatedNodes = nodes[startNode] ?: emptyList() + val currentPath: MutableList = mutableListOf() + for (i in relatedNodes.indices) { + for (j in i + 1 until relatedNodes.size) { + getPath(startNode, nodes, currentPath, relatedNodes[i], relatedNodes[j]) + getPath(startNode, nodes, currentPath, relatedNodes[j], relatedNodes[i]) + } + } + } + + private fun getPath(startNode: String, nodes: Map>, currentPath: List, currentNode: String, endNode: String) { + val nextNodes = nodes[currentNode] ?: emptyList() + if (nextNodes.isEmpty() || currentNode == startNode || currentNode == endNode) { + return + } + if (nextNodes.contains(endNode)) { + val path = listOf(startNode) + currentPath + listOf(currentNode, endNode) + totalPath.add(path.joinToString("->") + ";$startNode->$endNode") + } + for (node in nextNodes) { + if (currentPath.contains(node)) { + continue + } + getPath(startNode, nodes, currentPath + currentNode, node, endNode) + } + } + + private fun contains(list: List, element: String): Boolean { + return list.contains(element) + } +} diff --git a/unit-picker/src/main/kotlin/org/unimesh/eval/picker/bs/BadsmellAnalyser.kt b/unit-picker/src/main/kotlin/org/unimesh/eval/picker/bs/BadsmellAnalyser.kt index fd430f37..bae23828 100644 --- a/unit-picker/src/main/kotlin/org/unimesh/eval/picker/bs/BadsmellAnalyser.kt +++ b/unit-picker/src/main/kotlin/org/unimesh/eval/picker/bs/BadsmellAnalyser.kt @@ -1,9 +1,221 @@ package org.unimesh.eval.picker.bs import chapi.domain.core.CodeDataStruct +import chapi.domain.core.CodeFunction +import chapi.domain.core.CodePosition +import chapi.domain.core.DataStructType -class BadsmellAnalyser(val data: List) { - fun check() { +private val CodeFunction.IfSize: Int get() = 0 +private val CodeFunction.SwitchSize: Int get() = 0 +private val CodeFunction.IfInfo: CodePosition + get() { + return CodePosition(StartLine = this.Position.StartLine, StopLine = this.Position.StopLine) + } + +data class BsConfig( + val bsLongParasLength: Int = 5, + val bsIfSwitchLength: Int = 8, + val bsLargeLength: Int = 20, + val bsMethodLength: Int = 30, + val bsIfLinesLength: Int = 3, +) + +enum class SmellType { + SMELL_GARPH_CONNECTED_CALL, + SMELL_LAZY_ELEMENT, + SMELL_LONG_METHOD, + SMELL_DATA_CLASS, + SMELL_REFUSED_BEQUEST, + SMELL_LARGE_CLASS, + SMELL_COMPLEX_CONDITION, + SMELL_REPEATED_SWITCHES, + SMELL_LONG_PARAMETER_LIST +} + +data class BadSmellModel( + val file: String? = null, + val line: String? = null, + val bs: SmellType? = null, + val description: String? = null, + val size: Int? = null, +) + + +class BadsmellAnalyser(val data: List, val bsConfig: BsConfig = BsConfig()) { + fun analysis(): MutableList { + val badSmellList = mutableListOf() + for (node in data) { + checkLazyElement(node, badSmellList) + + var onlyHaveGetterAndSetter = true + for (method in node.Functions) { + checkLongMethod(method, node, badSmellList) + + if (!(method.isGetterSetter())) { + onlyHaveGetterAndSetter = false + } + + checkLongParameterList(method, node, badSmellList) + checkRepeatedSwitches(method, node, badSmellList) + checkComplexIf(method, node, badSmellList) + } + + checkDataClass(onlyHaveGetterAndSetter, node, badSmellList) + checkRefusedBequest(node, badSmellList) + checkLargeClass(node, badSmellList) + } + + checkConnectedGraphCall(data, badSmellList) + return badSmellList + } + + fun checkConnectedGraphCall(nodes: List, badSmellList: MutableList) { + val classNodes = mutableMapOf>() + val classNodeMaps = mutableMapOf() + for (node in nodes) { + classNodeMaps[node.getClassFullName()] = true + } + for (node in nodes) { + classNodes[node.getClassFullName()] = node.getCalledClasses(classNodeMaps) + } + val badSmellGraphCall = BadSmellGraphCall() + val descriptions = badSmellGraphCall.analysisGraphCallPath(classNodes) + for (description in descriptions) { + badSmellList.add(BadSmellModel(bs = SmellType.SMELL_GARPH_CONNECTED_CALL, description = description)) + } + } + + fun CodeDataStruct.getCalledClasses(maps: Map): List { + val calledClassesMap = mutableMapOf() + val calledClasses = mutableListOf() + for (methodCalled in this.FunctionCalls) { + if (methodCalled.NodeName == "" || !maps[methodCalled.buildClassFullName()]!! || this.getClassFullName() == methodCalled.buildClassFullName()) { + continue + } + calledClassesMap[methodCalled.buildClassFullName()] = true + } + for (key in calledClassesMap.keys) { + calledClasses.add(key) + } + + return calledClasses + } + + + fun checkLazyElement(node: CodeDataStruct, badSmellList: MutableList) { + if (node.Type == DataStructType.CLASS && node.Functions.isEmpty()) { + badSmellList.add(BadSmellModel(file = node.FilePath, bs = SmellType.SMELL_LAZY_ELEMENT)) + } + } + + fun checkLongMethod(method: CodeFunction, node: CodeDataStruct, badSmellList: MutableList) { + val methodLength = method.Position.StopLine - method.Position.StartLine + + if (methodLength > bsConfig.bsMethodLength) { + val description = "method length: $methodLength" + val longMethod = BadSmellModel( + file = node.FilePath, + line = method.Position.StartLine.toString(), + bs = SmellType.SMELL_LONG_METHOD, + description = description, + size = methodLength + ) + badSmellList.add(longMethod) + } + } + + fun checkDataClass( + onlyHaveGetterAndSetter: Boolean, + node: CodeDataStruct, + badSmellList: MutableList, + ) { + if (onlyHaveGetterAndSetter && node.Type == DataStructType.CLASS && node.Functions.isNotEmpty()) { + val dataClass = + BadSmellModel(file = node.FilePath, bs = SmellType.SMELL_DATA_CLASS, size = node.Functions.size) + badSmellList.add(dataClass) + } + } + + fun checkRefusedBequest(node: CodeDataStruct, badSmellList: MutableList) { + if (node.Extend != "" && node.HasCallSuper()) { + badSmellList.add(BadSmellModel(file = node.FilePath, bs = SmellType.SMELL_REFUSED_BEQUEST)) + } + } + + fun CodeDataStruct.HasCallSuper(): Boolean { + var hasCallSuperMethod = false + for (methodCall in this.FunctionCalls) { + if (methodCall.NodeName == this.Extend) { + hasCallSuperMethod = true + } + } + + return hasCallSuperMethod + } + + fun checkLargeClass(node: CodeDataStruct, badSmellList: MutableList) { + val normalClassLength = node.Functions.filter { !it.isGetterSetter() }.size + if (node.Type == DataStructType.CLASS && normalClassLength >= bsConfig.bsLargeLength) { + val description = "methods number (without getter/setter): $normalClassLength" + badSmellList.add( + BadSmellModel( + file = node.FilePath, + bs = SmellType.SMELL_LARGE_CLASS, + description = description, + size = normalClassLength + ) + ) + } + } + + fun checkComplexIf(method: CodeFunction, node: CodeDataStruct, badSmellList: MutableList) { + val info = method.IfInfo + if (info.StopLine - info.StartLine >= bsConfig.bsIfLinesLength) { + val longParams = BadSmellModel( + file = node.FilePath, + line = info.StartLine.toString(), + bs = SmellType.SMELL_COMPLEX_CONDITION, + description = SmellType.SMELL_COMPLEX_CONDITION.name + ) + badSmellList.add(longParams) + } + } + + fun checkRepeatedSwitches(method: CodeFunction, node: CodeDataStruct, badSmellList: MutableList) { + if (method.IfSize >= bsConfig.bsIfSwitchLength) { + val longParams = BadSmellModel( + file = node.FilePath, + line = method.Position.StartLine.toString(), + bs = SmellType.SMELL_REPEATED_SWITCHES, + description = "ifSize", + size = method.IfSize + ) + badSmellList.add(longParams) + } + + if (method.SwitchSize >= bsConfig.bsIfSwitchLength) { + val longParams = BadSmellModel( + file = node.FilePath, + line = method.Position.StartLine.toString(), + bs = SmellType.SMELL_REPEATED_SWITCHES, + description = "switchSize", + size = method.SwitchSize + ) + badSmellList.add(longParams) + } + } + fun checkLongParameterList(method: CodeFunction, node: CodeDataStruct, badSmellList: MutableList) { + if (method.Parameters.size > bsConfig.bsLongParasLength) { + val paramsJson = method.Parameters.joinToString(", ") + val longParams = BadSmellModel( + file = node.FilePath, + line = method.Position.StartLine.toString(), + bs = SmellType.SMELL_LONG_PARAMETER_LIST, + description = paramsJson, + size = method.Parameters.size + ) + badSmellList.add(longParams) + } } } \ No newline at end of file diff --git a/unit-picker/src/test/kotlin/org/unimesh/eval/picker/bs/BsAnalyser.kt b/unit-picker/src/test/kotlin/org/unimesh/eval/picker/bs/BsAnalyser.kt new file mode 100644 index 00000000..fb911244 --- /dev/null +++ b/unit-picker/src/test/kotlin/org/unimesh/eval/picker/bs/BsAnalyser.kt @@ -0,0 +1,47 @@ +package org.unimesh.eval.picker.bs + +import chapi.ast.javaast.JavaAnalyser +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import java.io.File +import java.nio.file.Paths + +class BsAnalyserTest { + private fun getAbsolutePath(path: String): String { + val resource = this.javaClass.classLoader.getResource(path) + return Paths.get(resource!!.toURI()).toFile().absolutePath + } + + @Test + internal fun shouldIdentifyJavaEmptyTest() { + val path = getAbsolutePath("bs/LazyClass.java") + val data = JavaAnalyser().analysis(File(path).readText(), "LazyClass.java").DataStructures + val results = BadsmellAnalyser(data).analysis() + + assertEquals(1, results.size) + assertEquals("LazyClass.java", results[0].file) + assertEquals(SmellType.SMELL_LAZY_ELEMENT, results[0].bs) + } + + @Test + fun shouldIdentifyLongParameters() { + val path = getAbsolutePath("bs/LongParameter.java") + val data = JavaAnalyser().analysis(File(path).readText(), "LongParameter.java").DataStructures + val results = BadsmellAnalyser(data).analysis() + + assertEquals(1, results.size) + assertEquals("LongParameter.java", results[0].file) + assertEquals(SmellType.SMELL_LONG_PARAMETER_LIST, results[0].bs) + } + + @Test + fun shouldIdentifyMultipleIf() { + val path = getAbsolutePath("bs/MultipleIf.java") + val data = JavaAnalyser().analysis(File(path).readText(), "MultipleIf.java").DataStructures + val results = BadsmellAnalyser(data).analysis() + + assertEquals(1, results.size) + assertEquals("MultipleIf.java", results[0].file) + assertEquals(SmellType.SMELL_COMPLEX_CONDITION, results[0].bs) + } +} \ No newline at end of file diff --git a/unit-picker/src/test/resources/bs/ComplexIf.java b/unit-picker/src/test/resources/bs/ComplexIf.java new file mode 100644 index 00000000..f434c579 --- /dev/null +++ b/unit-picker/src/test/resources/bs/ComplexIf.java @@ -0,0 +1,70 @@ +package com.zheng.upms.server.controller.manage; + +import com.baidu.unbiz.fluentvalidator.ComplexResult; +import com.baidu.unbiz.fluentvalidator.FluentValidator; +import com.baidu.unbiz.fluentvalidator.ResultCollectors; +import com.zheng.common.base.BaseController; +import com.zheng.common.validator.LengthValidator; +import com.zheng.upms.common.constant.UpmsResult; +import com.zheng.upms.common.constant.UpmsResultConstant; +import com.zheng.upms.dao.model.UpmsSystem; +import com.zheng.upms.dao.model.UpmsSystemExample; +import com.zheng.upms.rpc.api.UpmsSystemService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang.StringUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 系统controller + * Created by shuzheng on 2016/12/18. + */ +@Controller +@Api(value = "系统管理", description = "系统管理") +@RequestMapping("/manage/system") +public class UpmsSystemController extends BaseController { + + private static final Logger LOGGER = LoggerFactory.getLogger(UpmsSystemController.class); + + @Autowired + private UpmsSystemService upmsSystemService; + + @ApiOperation(value = "系统列表") + @RequiresPermissions("upms:system:read") + @RequestMapping(value = "/list", method = RequestMethod.GET) + @ResponseBody + public Object list( + @RequestParam(required = false, defaultValue = "0", value = "offset") int offset, + @RequestParam(required = false, defaultValue = "10", value = "limit") int limit, + @RequestParam(required = false, defaultValue = "", value = "search") String search, + @RequestParam(required = false, value = "sort") String sort, + @RequestParam(required = false, value = "order") String order) { + UpmsSystemExample upmsSystemExample = new UpmsSystemExample(); + if (!StringUtils.isBlank(sort) + && !StringUtils.isBlank(order) + + ) { + upmsSystemExample.setOrderByClause(sort + " " + order); + } + if (StringUtils.isNotBlank(search)) { + upmsSystemExample.or() + .andTitleLike("%" + search + "%"); + } + List rows = upmsSystemService.selectByExampleForOffsetPage(upmsSystemExample, offset, limit); + long total = upmsSystemService.countByExample(upmsSystemExample); + Map result = new HashMap<>(); + result.put("rows", rows); + result.put("total", total); + return result; + } +} diff --git a/unit-picker/src/test/resources/bs/DataClass.java b/unit-picker/src/test/resources/bs/DataClass.java new file mode 100644 index 00000000..a410a3af --- /dev/null +++ b/unit-picker/src/test/resources/bs/DataClass.java @@ -0,0 +1,22 @@ +package com.phodal.coca.analysis.identifier.model; + +public class DataClass { + private String date; + private String time; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } +} diff --git a/unit-picker/src/test/resources/bs/LargeClass.java b/unit-picker/src/test/resources/bs/LargeClass.java new file mode 100644 index 00000000..9f3fec6d --- /dev/null +++ b/unit-picker/src/test/resources/bs/LargeClass.java @@ -0,0 +1,24 @@ +package com.phodal.coca.analysis.identifier.model; + +public class DataClass { + public void method1() {} + public void method2() {} + public void method3() {} + public void method4() {} + public void method5() {} + public void method6() {} + public void method7() {} + public void method8() {} + public void method9() {} + public void method10() {} + public void method11() {} + public void method12() {} + public void method13() {} + public void method14() {} + public void method15() {} + public void method16() {} + public void method17() {} + public void method18() {} + public void method19() {} + public void method20() {} +} diff --git a/unit-picker/src/test/resources/bs/LazyClass.java b/unit-picker/src/test/resources/bs/LazyClass.java new file mode 100644 index 00000000..80f15f9f --- /dev/null +++ b/unit-picker/src/test/resources/bs/LazyClass.java @@ -0,0 +1,3 @@ +class LazyClass { + +} diff --git a/unit-picker/src/test/resources/bs/LongMethod.java b/unit-picker/src/test/resources/bs/LongMethod.java new file mode 100644 index 00000000..38024cdd --- /dev/null +++ b/unit-picker/src/test/resources/bs/LongMethod.java @@ -0,0 +1,227 @@ +package evolution.analysis.jv.calls; + +import evolution.analysis.jv.JavaParser; +import evolution.analysis.jv.JavaParserBaseVisitor; +import evolution.analysis.jv.calls.model.JMethodCall; +import org.antlr.v4.runtime.tree.ParseTree; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +public class JavaCallVisitor extends JavaParserBaseVisitor { + + private static final Logger LOGGER = Logger.getLogger(JavaCallVisitor.class.getName()); + private Map fields = new HashMap<>(); + private Map formalParameters = new HashMap<>(); + private Map localVars = new HashMap<>(); + private String currentClz = null; + private String currentPkg = null; + private List imports = new ArrayList<>(); + private JavaDaoParser daoParser; + + private final List clzs; + private JMethodCall currentMethodCall; + + private List methodCalls; + + public JavaCallVisitor(List methodCalls,List clzs,JavaDaoParser daoParser) { + this.clzs = clzs; + this.methodCalls = methodCalls; + this.daoParser = daoParser; + } + + @Override + public Object visitPackageDeclaration(evolution.analysis.jv.JavaParser.PackageDeclarationContext ctx) { + currentPkg = ctx.qualifiedName().getText(); + return super.visitPackageDeclaration(ctx); + } + + @Override + public Object visitImportDeclaration(evolution.analysis.jv.JavaParser.ImportDeclarationContext ctx) { + imports.add(ctx.qualifiedName().getText()); + return super.visitImportDeclaration(ctx); + } + + @Override + public Object visitClassDeclaration(evolution.analysis.jv.JavaParser.ClassDeclarationContext ctx) { + currentClz = ctx.IDENTIFIER().getText(); + return super.visitClassDeclaration(ctx); + } + + @Override + public Object visitTypeDeclaration(evolution.analysis.jv.JavaParser.TypeDeclarationContext ctx) { + //System.out.println(ctx.getText()); + return super.visitTypeDeclaration(ctx); + } + + @Override public Object visitInterfaceDeclaration(JavaParser.InterfaceDeclarationContext ctx) { + currentClz = ctx.IDENTIFIER().getText(); + return super.visitChildren(ctx); + } + + @Override public Object visitInterfaceMethodDeclaration(JavaParser.InterfaceMethodDeclarationContext ctx) { + currentMethodCall = new JMethodCall(); + methodCalls.add(currentMethodCall); + currentMethodCall.setPkg(currentPkg); + currentMethodCall.setClz(currentClz); + currentMethodCall.setMethodName(ctx.IDENTIFIER().getText()); + daoParser.parse(currentMethodCall,ctx.IDENTIFIER().getText()); + return super.visitChildren(ctx); + } + + @Override + public Object visitMethodDeclaration(evolution.analysis.jv.JavaParser.MethodDeclarationContext ctx) { + //System.out.println("\nMethod: " + ctx.IDENTIFIER().getText()); + currentMethodCall = new JMethodCall(); + methodCalls.add(currentMethodCall); + currentMethodCall.setPkg(currentPkg); + currentMethodCall.setClz(currentClz); + currentMethodCall.setMethodName(ctx.IDENTIFIER().getText()); + + String body = ctx.getText().toUpperCase(); + daoParser.parse(currentMethodCall,body); + + return super.visitMethodDeclaration(ctx); + } + + @Override + public Object visitMethodCall(evolution.analysis.jv.JavaParser.MethodCallContext ctx) { + + if (currentMethodCall != null) { + ParseTree targetCtx = ctx.getParent().getChild(0); + String targetVar = targetCtx.getText(); + String targetType1 = targetVar; + String parentCtxClz = targetCtx.getClass().getCanonicalName(); + if ("me.analysis.jv.JavaParser.MethodCallContext".equals(parentCtxClz)) { + targetType1 = currentClz; + } else if ("this".equalsIgnoreCase(targetVar)) { + targetType1 = currentClz; + } else if (targetVar.matches(".*new.*\\)\\..*") && isNotSpecialNewWord(targetVar)) { + try { + targetType1 = parseNewType(targetCtx); + //System.out.println("Matched: " + targetVar + " , " +targetType); + } catch (NullPointerException e) { + //not create object new method. but name include new word. + LOGGER.info(ctx.getParent().getText()); + //System.out.println(currentClz + " . " + currentMethodCall.getMethodName()); + //System.out.println(targetCtx.getText()); + LOGGER.info(e.getMessage()); + } + } else { + String fieldType = fields.get(targetVar); + String formalType = formalParameters.get(targetVar); + String localVarType = localVars.get(targetVar); + if (fieldType != null) { + targetType1 = fieldType; + } else if (formalType != null) { + targetType1 = formalType; + } else if (localVarType != null) { + targetType1 = localVarType; + } + } + String targetType = targetType1; + String callee = ctx.getChild(0).getText(); + + String warpTargetFullType = null; + if (currentClz.equalsIgnoreCase(targetType)) { + warpTargetFullType = currentPkg + "." + targetType; + } else { + for (String imp : imports) { + if (imp.endsWith(targetType)) { + warpTargetFullType = imp; + break; + } + } + if (warpTargetFullType == null) {//maybe the same package + for (String c : clzs) { + if (c.endsWith(targetType)) { + warpTargetFullType = c; + break; + } + }//1. current package, 2. import by * + } + } + if(warpTargetFullType != null) { + currentMethodCall.addMethodCall(warpTargetFullType, callee); + } else { + //System.out.println("Can not wrap:\t" + targetType); + } + + } + return super.visitMethodCall(ctx); + } + + private boolean isNotSpecialNewWord(String targetVar) { + return !targetVar.contains("inspectionnew") && !targetVar.contains("renew") && !targetVar.contains("Renew") + && !targetVar.contains("newcoverages") && !targetVar.contains("newCoverages"); + } + + private String parseNewType(ParseTree ctx) { + ParseTree creatorCxt = getJavaParserCreatorCxt(ctx); + return creatorCxt.getChild(0).getText(); + } + + private ParseTree getJavaParserCreatorCxt(ParseTree ctx) { + if ("me.analysis.jv.JavaParser.CreatorContext".equals(ctx.getClass().getCanonicalName())) { + return ctx; + } else { + ParseTree res = null; + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree c = getJavaParserCreatorCxt(ctx.getChild(i)); + if (c != null) { + res = c; + break; + } + } + return res; + } + } + + @Override + public Object visitFormalParameters(evolution.analysis.jv.JavaParser.FormalParametersContext ctx) { + //System.out.println(ctx.getText()); + return super.visitFormalParameters(ctx); + } + + @Override + public Object visitFormalParameter(evolution.analysis.jv.JavaParser.FormalParameterContext ctx) { + //System.out.println(ctx.typeType().getText() + ":" + ctx.variableDeclaratorId().getText() + "@me.analysis.jv.JavaParser.FormalParameterContext"); + formalParameters.put(ctx.variableDeclaratorId().getText(), ctx.typeType().getText()); + return super.visitFormalParameter(ctx); + } + + @Override + public Object visitFieldDeclaration(evolution.analysis.jv.JavaParser.FieldDeclarationContext ctx) { + JavaParser.VariableDeclaratorsContext variableDeclaratorsContext = ctx.variableDeclarators(); + String variableName = variableDeclaratorsContext.getChild(0).getChild(0).getText(); + //System.out.println(ctx.typeType().getText() + ":" + variableName); + fields.put(variableName, ctx.typeType().getText()); + return super.visitFieldDeclaration(ctx); + } + + @Override + public Object visitLocalVariableDeclaration(JavaParser.LocalVariableDeclarationContext ctx) { + String typ = ctx.getChild(0).getText(); + String variableName = ctx.getChild(1).getChild(0).getChild(0).getText(); + localVars.put(variableName, typ); + return super.visitChildren(ctx); + } + + @Override + public Object visitVariableDeclarators(evolution.analysis.jv.JavaParser.VariableDeclaratorsContext ctx) { + return super.visitVariableDeclarators(ctx); + } + + @Override + public Object visitArguments(evolution.analysis.jv.JavaParser.ArgumentsContext ctx) { + //调其他方法的参数 +// System.out.println("===="); +// System.out.println(ctx.getText()+"@me.analysis.jv.JavaParser.ArgumentsContext"); +// System.out.println("===="); + return super.visitArguments(ctx); + } + +} diff --git a/unit-picker/src/test/resources/bs/LongParameter.java b/unit-picker/src/test/resources/bs/LongParameter.java new file mode 100644 index 00000000..9ece43e0 --- /dev/null +++ b/unit-picker/src/test/resources/bs/LongParameter.java @@ -0,0 +1,7 @@ +package com.phodal.coca.analysis.identifier.model; + +public class LongParameter { + public void buildSomeThing(String time, int x, int y, int z, int a, int b) { + + } +} diff --git a/unit-picker/src/test/resources/bs/MultipleIf.java b/unit-picker/src/test/resources/bs/MultipleIf.java new file mode 100644 index 00000000..42b6ba3a --- /dev/null +++ b/unit-picker/src/test/resources/bs/MultipleIf.java @@ -0,0 +1,24 @@ +class MultipleIf { + public static void main(String args[]) { + int i = 20; + + if (i == 10) + System.out.println("i is 10"); + if (i == 15) + System.out.println("i is 15"); + if (i == 20) + System.out.println("i is 20"); + if (i == 20) + System.out.println("i is 20"); + if (i == 20) + System.out.println("i is 20"); + if (i == 20) + System.out.println("i is 20"); + if (i == 20) + System.out.println("i is 20"); + if (i == 20) + System.out.println("i is 20"); + else + System.out.println("i is not present"); + } +} diff --git a/unit-picker/src/test/resources/bs/graphcall/GraphCallA.java b/unit-picker/src/test/resources/bs/graphcall/GraphCallA.java new file mode 100644 index 00000000..55bd0285 --- /dev/null +++ b/unit-picker/src/test/resources/bs/graphcall/GraphCallA.java @@ -0,0 +1,12 @@ + +package graphcall; + +public class GraphCallA { + private GraphCallB graphCallB; + private GraphCallC graphCallC; + + public void sayHi(){ + graphCallB.sayHi(); + graphCallC.sayHi(); + } +} diff --git a/unit-picker/src/test/resources/bs/graphcall/GraphCallB.java b/unit-picker/src/test/resources/bs/graphcall/GraphCallB.java new file mode 100644 index 00000000..7dfe233e --- /dev/null +++ b/unit-picker/src/test/resources/bs/graphcall/GraphCallB.java @@ -0,0 +1,9 @@ +package graphcall; + +public class GraphCallB { + private GraphCallC graphCallC; + + public void sayHi(){ + graphCallC.sayHi(); + } +} diff --git a/unit-picker/src/test/resources/bs/graphcall/GraphCallC.java b/unit-picker/src/test/resources/bs/graphcall/GraphCallC.java new file mode 100644 index 00000000..8db977dd --- /dev/null +++ b/unit-picker/src/test/resources/bs/graphcall/GraphCallC.java @@ -0,0 +1,8 @@ +package graphcall; + +public class GraphCallC { + + public void sayHi(){ + System.out.println("hi"); + } +} diff --git a/unit-picker/src/test/resources/bs/interface/BlogRepository.java b/unit-picker/src/test/resources/bs/interface/BlogRepository.java new file mode 100644 index 00000000..f072bd09 --- /dev/null +++ b/unit-picker/src/test/resources/bs/interface/BlogRepository.java @@ -0,0 +1,19 @@ +package study.huhao.demo.domain.models.blog; + +import study.huhao.demo.domain.core.Page; +import study.huhao.demo.domain.core.Repository; + +import java.util.Optional; +import java.util.UUID; + +public interface BlogRepository extends Repository { + void save(Blog blog); + + Optional findById(UUID id); + + boolean existsById(UUID id); + + void deleteById(UUID id); + + Page findAllWithPagination(BlogCriteria criteria); +}