From 3e67cbf5ac0e6cdeebb68b35a263e1415df910a6 Mon Sep 17 00:00:00 2001 From: Phodal Huang Date: Tue, 5 Nov 2019 19:14:48 +0800 Subject: [PATCH] feat: add some refactor code --- bs/BadSmellApp.go | 33 ++++++++- bs/BadSmellListener.go | 77 ++++++++++++++++++--- bs/models/BsModel.go | 16 ++++- bs/{ => run}/main.go | 1 + examples/bs/DataClass.java | 22 ++++++ examples/bs/MultipleIf.java | 24 +++++++ refactor/unused_classes/UnusedClassesApp.go | 50 +++++++++++++ 7 files changed, 211 insertions(+), 12 deletions(-) rename bs/{ => run}/main.go (89%) create mode 100644 examples/bs/DataClass.java create mode 100644 examples/bs/MultipleIf.java create mode 100644 refactor/unused_classes/UnusedClassesApp.go diff --git a/bs/BadSmellApp.go b/bs/BadSmellApp.go index dd16cfa..e114cd9 100644 --- a/bs/BadSmellApp.go +++ b/bs/BadSmellApp.go @@ -1,4 +1,4 @@ -package main +package bs import ( "encoding/json" @@ -63,6 +63,7 @@ func analysisBadSmell(nodes []JFullClassNode) []BadSmellModel { badSmellList = append(badSmellList, *&BadSmellModel{node.Path, "", "lazyElement"}) } + onlyHaveGetterAndSetter := true // Long Method for _, method := range node.Methods { if method.StopLine-method.StartLine > 50 { @@ -70,11 +71,41 @@ func analysisBadSmell(nodes []JFullClassNode) []BadSmellModel { badSmellList = append(badSmellList, *longMethod) } + if strings.Contains(method.Name, "get") && strings.Contains(method.Name, "set") { + onlyHaveGetterAndSetter = false + } + // longParameterList if len(method.Parameters) > 6 { longParams := &BadSmellModel{node.Path, strconv.Itoa(method.StartLine), "longParameterList"} badSmellList = append(badSmellList, *longParams) } + + // longParameterList + if method.MethodBs.IfSize > 8 || method.MethodBs.SwitchSize > 8 { + longParams := &BadSmellModel{node.Path, strconv.Itoa(method.StartLine), "repeatedSwitches"} + badSmellList = append(badSmellList, *longParams) + } + } + + fmt.Println(onlyHaveGetterAndSetter, node.Type, len(node.Methods)) + if onlyHaveGetterAndSetter && node.Type == "Class" && len(node.Methods) > 0 { + dataClass := &BadSmellModel{node.Path, "", "dataClass"} + badSmellList = append(badSmellList, *dataClass) + } + + //Refused Bequest + if node.Extends != "" { + hasCallParentMethod := false + for _, methodCall := range node.MethodCalls { + if methodCall.Class == node.Extends { + hasCallParentMethod = true + } + } + + if !hasCallParentMethod { + badSmellList = append(badSmellList, *&BadSmellModel{node.Path, "", "refusedBequest"}) + } } // LargeClass diff --git a/bs/BadSmellListener.go b/bs/BadSmellListener.go index fad1657..69c0fc7 100644 --- a/bs/BadSmellListener.go +++ b/bs/BadSmellListener.go @@ -1,4 +1,4 @@ -package main +package bs import ( "github.com/antlr/antlr4/runtime/Go/antlr" @@ -12,9 +12,13 @@ var imports []string var clzs []string var currentPkg string var currentClz string +var currentClzType string + +var currentClzExtends string +var currentClzImplements []string + var methods []JFullMethod var methodCalls []JFullMethodCall -var currentType string var fields = make(map[string]string) var localVars = make(map[string]string) @@ -26,6 +30,8 @@ func NewBadSmellListener() *BadSmellListener { currentPkg = "" methods = nil methodCalls = nil + currentClzImplements = nil + currentClzExtends = "" return &BadSmellListener{} } @@ -37,8 +43,10 @@ func (s *BadSmellListener) getNodeInfo() *JFullClassNode { return &JFullClassNode{ currentPkg, currentClz, - currentType, + currentClzType, "", + currentClzExtends, + currentClzImplements, methods, methodCalls, currentClassBs, @@ -55,12 +63,35 @@ func (s *BadSmellListener) EnterImportDeclaration(ctx *ImportDeclarationContext) } func (s *BadSmellListener) EnterClassDeclaration(ctx *ClassDeclarationContext) { - currentType = "Class" + currentClzType = "Class" currentClz = ctx.IDENTIFIER().GetText() + + if ctx.EXTENDS() != nil { + currentClzExtends = ctx.TypeType().GetText() + } + + if ctx.IMPLEMENTS() != nil { + typeList := ctx.TypeList().(*TypeListContext) + for _, typ := range typeList.AllTypeType() { + typeData := getTypeDATA(typ.(*TypeTypeContext)) + currentClzImplements = append(currentClzImplements, typeData) + } + } +} + +func getTypeDATA(typ *TypeTypeContext) string { + var typeData string + classOrInterface := typ.ClassOrInterfaceType().(*ClassOrInterfaceTypeContext) + if classOrInterface != nil { + identifiers := classOrInterface.AllIDENTIFIER() + typeData = identifiers[len(identifiers)-1].GetText() + } + + return typeData } func (s *BadSmellListener) EnterInterfaceDeclaration(ctx *InterfaceDeclarationContext) { - currentType = "Interface" + currentClzType = "Interface" currentClz = ctx.IDENTIFIER().GetText() } @@ -149,6 +180,7 @@ func (s *BadSmellListener) EnterMethodDeclaration(ctx *MethodDeclarationContext) } methodBSInfo := *&MethodBadSmellInfo{0, 0} + methodBadSmellInfo := buildMethodBSInfo(ctx, methodBSInfo) method := &JFullMethod{ name, @@ -159,19 +191,48 @@ func (s *BadSmellListener) EnterMethodDeclaration(ctx *MethodDeclarationContext) stopLinePosition, methodBody, methodParams, - methodBSInfo, + methodBadSmellInfo, } methods = append(methods, *method) } +func buildMethodBSInfo(context *MethodDeclarationContext, bsInfo MethodBadSmellInfo) MethodBadSmellInfo { + methodBody := context.MethodBody() + blockContext := methodBody.GetChild(0) + if reflect.TypeOf(blockContext).String() == "*parser.BlockContext" { + blcStatement := blockContext.(*BlockContext).AllBlockStatement() + for _, statement := range blcStatement { + if reflect.TypeOf(statement.GetChild(0)).String() == "*parser.StatementContext" { + if len(statement.GetChild(0).(*StatementContext).GetChildren()) < 3 { + continue + } + + statementCtx := statement.GetChild(0).(*StatementContext) + if (reflect.TypeOf(statementCtx.GetChild(1)).String()) == "*parser.ParExpressionContext" { + if statementCtx.GetChild(0).(antlr.ParseTree).GetText() == "if" { + bsInfo.IfSize = bsInfo.IfSize + 1 + } + + if statementCtx.GetChild(0).(antlr.ParseTree).GetText() == "switch" { + bsInfo.SwitchSize = bsInfo.SwitchSize + 1 + } + + } + } + } + } + + return bsInfo +} + func (s *BadSmellListener) EnterFormalParameterList(ctx *FormalParameterListContext) { //fmt.Println(ctx.GetParent().GetParent().(antlr.RuleNode).get) //fmt.Println(ctx.AllFormalParameter() } func (s *BadSmellListener) EnterAnnotation(ctx *AnnotationContext) { - if currentType == "Class" && ctx.QualifiedName().GetText() == "Override" { - + if currentClzType == "Class" && ctx.QualifiedName().GetText() == "Override" { + currentClassBs.OverrideSize++ } } diff --git a/bs/models/BsModel.go b/bs/models/BsModel.go index 1d0d8dd..78a8760 100644 --- a/bs/models/BsModel.go +++ b/bs/models/BsModel.go @@ -5,6 +5,8 @@ type JFullClassNode struct { Class string Type string Path string + Extends string + Implements []string Methods []JFullMethod MethodCalls []JFullMethodCall ClassBS ClassBadSmellInfo @@ -34,8 +36,8 @@ type JFullMethod struct { } type MethodBadSmellInfo struct { - SwitchSize int IfSize int + SwitchSize int } type ClassBadSmellInfo struct { @@ -48,8 +50,16 @@ type JFullParameter struct { Type string } - func NewJFullClassNode() *JFullClassNode { info := &ClassBadSmellInfo{0, 0}; - return &JFullClassNode{"", "", "", "", nil, nil, *info} + return &JFullClassNode{ + "", + "", + "", + "", + "", + nil, + nil, + nil, + *info} } diff --git a/bs/main.go b/bs/run/main.go similarity index 89% rename from bs/main.go rename to bs/run/main.go index 75f56ee..abe7d4e 100644 --- a/bs/main.go +++ b/bs/run/main.go @@ -2,6 +2,7 @@ package main import ( "encoding/json" + . "github.com/phodal/coca/bs" . "github.com/phodal/coca/utils" ) diff --git a/examples/bs/DataClass.java b/examples/bs/DataClass.java new file mode 100644 index 0000000..a410a3a --- /dev/null +++ b/examples/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/examples/bs/MultipleIf.java b/examples/bs/MultipleIf.java new file mode 100644 index 0000000..5e32b9b --- /dev/null +++ b/examples/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"); + else if (i == 15) + System.out.println("i is 15"); + else 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/refactor/unused_classes/UnusedClassesApp.go b/refactor/unused_classes/UnusedClassesApp.go new file mode 100644 index 0000000..475d7d4 --- /dev/null +++ b/refactor/unused_classes/UnusedClassesApp.go @@ -0,0 +1,50 @@ +package main + +import ( + "encoding/json" + "fmt" + . "github.com/phodal/coca/adapter/models" + . "github.com/phodal/coca/utils" + "sort" + "strings" +) + +var parsedDeps []JClassNode + +func main() { + var analysisPackage = "" + file := ReadFile("deps.json") + if file == nil { + return + } + + _ = json.Unmarshal(file, &parsedDeps) + sourceClasses := make(map[string]string) + targetlasses := make(map[string]string) + + for _, node := range parsedDeps { + if strings.Contains(node.Package, analysisPackage) { + className := node.Package + "." + node.Class + sourceClasses[className] = className + } + + for _, methodCall := range node.MethodCalls { + if strings.Contains(methodCall.Package, analysisPackage) { + className := methodCall.Package + "." + methodCall.Class + targetlasses[className] = className + } + } + } + + var excludePackage []string = nil + for _, clz := range sourceClasses { + if targetlasses[clz] != clz { + excludePackage = append(excludePackage, clz) + } + } + + sort.Sort(sort.StringSlice(excludePackage)) + for _, res := range excludePackage { + fmt.Println(res) + } +} -- GitLab