Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Phodal
Coca
提交
320ca995
C
Coca
项目概览
Phodal
/
Coca
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
Coca
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
320ca995
编写于
11月 04, 2019
作者:
P
Phodal Huang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: add a basic bad smell examples
上级
61ac3a93
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
298 addition
and
39 deletion
+298
-39
bs/BadSmellApp.go
bs/BadSmellApp.go
+84
-0
bs/BadSmellListener.go
bs/BadSmellListener.go
+200
-0
bs/bs.go
bs/bs.go
+0
-32
cmd/badsmell.go
cmd/badsmell.go
+14
-7
未找到文件。
bs/BadSmellApp.go
0 → 100644
浏览文件 @
320ca995
package
call
import
(
"fmt"
"github.com/antlr/antlr4/runtime/Go/antlr"
"os"
"path/filepath"
"strings"
.
"github.com/phodal/coca/adapter/models"
.
"github.com/phodal/coca/language/java"
)
var
nodeInfos
[]
JClassNode
type
BadSmellModel
struct
{
File
string
Line
string
Bs
string
}
type
BadSmellApp
struct
{
}
func
(
j
*
BadSmellApp
)
AnalysisPath
(
codeDir
string
)
[]
BadSmellModel
{
nodeInfos
=
nil
files
:=
(
*
BadSmellApp
)(
nil
)
.
javaFiles
(
codeDir
)
for
index
:=
range
files
{
nodeInfo
:=
NewClassNode
()
file
:=
files
[
index
]
displayName
:=
filepath
.
Base
(
file
)
fmt
.
Println
(
"Start parse java call: "
+
displayName
)
parser
:=
(
*
BadSmellApp
)(
nil
)
.
processFile
(
file
)
context
:=
parser
.
CompilationUnit
()
listener
:=
NewBadSmellListener
()
antlr
.
NewParseTreeWalker
()
.
Walk
(
listener
,
context
)
nodeInfo
=
listener
.
getNodeInfo
()
nodeInfo
.
Path
=
file
nodeInfos
=
append
(
nodeInfos
,
*
nodeInfo
)
}
bsList
:=
analysisBadSmell
(
nodeInfos
)
return
bsList
}
func
analysisBadSmell
(
nodes
[]
JClassNode
)
[]
BadSmellModel
{
var
badSmellList
[]
BadSmellModel
for
_
,
node
:=
range
nodes
{
for
_
,
method
:=
range
node
.
Methods
{
if
method
.
StartLine
-
method
.
StopLine
>
50
{
longMethod
:=
&
BadSmellModel
{
node
.
Path
,
string
(
method
.
StartLine
),
"longMethod"
}
badSmellList
=
append
(
badSmellList
,
*
longMethod
)
}
}
}
return
badSmellList
;
return
nil
}
func
(
j
*
BadSmellApp
)
javaFiles
(
codeDir
string
)
[]
string
{
files
:=
make
([]
string
,
0
)
_
=
filepath
.
Walk
(
codeDir
,
func
(
path
string
,
fi
os
.
FileInfo
,
err
error
)
error
{
if
strings
.
HasSuffix
(
path
,
".java"
)
&&
!
strings
.
Contains
(
path
,
"Test.java"
)
{
files
=
append
(
files
,
path
)
}
return
nil
})
return
files
}
func
(
j
*
BadSmellApp
)
processFile
(
path
string
)
*
JavaParser
{
is
,
_
:=
antlr
.
NewFileStream
(
path
)
lexer
:=
NewJavaLexer
(
is
)
stream
:=
antlr
.
NewCommonTokenStream
(
lexer
,
0
);
parser
:=
NewJavaParser
(
stream
)
return
parser
}
bs/BadSmellListener.go
0 → 100644
浏览文件 @
320ca995
package
call
import
(
"github.com/antlr/antlr4/runtime/Go/antlr"
.
"github.com/phodal/coca/adapter/models"
.
"github.com/phodal/coca/language/java"
"reflect"
"strings"
)
var
imports
[]
string
var
clzs
[]
string
var
currentPkg
string
var
currentClz
string
var
methods
[]
JMethod
var
methodCalls
[]
JMethodCall
var
currentType
string
var
fields
=
make
(
map
[
string
]
string
)
var
localVars
=
make
(
map
[
string
]
string
)
var
formalParameters
=
make
(
map
[
string
]
string
)
func
NewBadSmellListener
()
*
BadSmellListener
{
currentClz
=
""
currentPkg
=
""
methods
=
nil
methodCalls
=
nil
return
&
BadSmellListener
{}
}
type
BadSmellListener
struct
{
BaseJavaParserListener
}
func
(
s
*
BadSmellListener
)
getNodeInfo
()
*
JClassNode
{
return
&
JClassNode
{
currentPkg
,
currentClz
,
currentType
,
""
,
methods
,
methodCalls
}
}
func
(
s
*
BadSmellListener
)
EnterPackageDeclaration
(
ctx
*
PackageDeclarationContext
)
{
currentPkg
=
ctx
.
QualifiedName
()
.
GetText
()
}
func
(
s
*
BadSmellListener
)
EnterImportDeclaration
(
ctx
*
ImportDeclarationContext
)
{
importText
:=
ctx
.
QualifiedName
()
.
GetText
()
imports
=
append
(
imports
,
importText
)
}
func
(
s
*
BadSmellListener
)
EnterClassDeclaration
(
ctx
*
ClassDeclarationContext
)
{
currentType
=
"Class"
currentClz
=
ctx
.
IDENTIFIER
()
.
GetText
()
}
func
(
s
*
BadSmellListener
)
EnterInterfaceDeclaration
(
ctx
*
InterfaceDeclarationContext
)
{
currentType
=
"Interface"
currentClz
=
ctx
.
IDENTIFIER
()
.
GetText
()
}
func
(
s
*
BadSmellListener
)
EnterInterfaceMethodDeclaration
(
ctx
*
InterfaceMethodDeclarationContext
)
{
startLine
:=
ctx
.
GetStart
()
.
GetLine
()
startLinePosition
:=
ctx
.
IDENTIFIER
()
.
GetSymbol
()
.
GetColumn
()
stopLine
:=
ctx
.
GetStop
()
.
GetLine
()
name
:=
ctx
.
IDENTIFIER
()
.
GetText
()
stopLinePosition
:=
startLinePosition
+
len
(
name
)
typeType
:=
ctx
.
TypeTypeOrVoid
()
.
GetText
()
method
:=
&
JMethod
{
name
,
typeType
,
startLine
,
startLinePosition
,
stopLine
,
stopLinePosition
}
methods
=
append
(
methods
,
*
method
)
}
func
(
s
*
BadSmellListener
)
EnterFormalParameter
(
ctx
*
FormalParameterContext
)
{
formalParameters
[
ctx
.
VariableDeclaratorId
()
.
GetText
()]
=
ctx
.
TypeType
()
.
GetText
()
}
func
(
s
*
BadSmellListener
)
EnterFieldDeclaration
(
ctx
*
FieldDeclarationContext
)
{
declarators
:=
ctx
.
VariableDeclarators
()
variableName
:=
declarators
.
GetParent
()
.
GetChild
(
0
)
.
(
antlr
.
ParseTree
)
.
GetText
()
fields
[
variableName
]
=
ctx
.
TypeType
()
.
GetText
()
}
func
(
s
*
BadSmellListener
)
EnterLocalVariableDeclaration
(
ctx
*
LocalVariableDeclarationContext
)
{
typ
:=
ctx
.
GetChild
(
0
)
.
(
antlr
.
ParseTree
)
.
GetText
()
variableName
:=
ctx
.
GetChild
(
1
)
.
GetChild
(
0
)
.
GetChild
(
0
)
.
(
antlr
.
ParseTree
)
.
GetText
()
localVars
[
variableName
]
=
typ
}
func
(
s
*
BadSmellListener
)
EnterMethodDeclaration
(
ctx
*
MethodDeclarationContext
)
{
startLine
:=
ctx
.
GetStart
()
.
GetLine
()
startLinePosition
:=
ctx
.
IDENTIFIER
()
.
GetSymbol
()
.
GetColumn
()
stopLine
:=
ctx
.
GetStop
()
.
GetLine
()
name
:=
ctx
.
IDENTIFIER
()
.
GetText
()
stopLinePosition
:=
startLinePosition
+
len
(
name
)
//XXX: find the start position of {, not public
typeType
:=
ctx
.
TypeTypeOrVoid
()
.
GetText
()
method
:=
&
JMethod
{
name
,
typeType
,
startLine
,
startLinePosition
,
stopLine
,
stopLinePosition
}
methods
=
append
(
methods
,
*
method
)
}
func
(
s
*
BadSmellListener
)
EnterMethodCall
(
ctx
*
MethodCallContext
)
{
var
targetCtx
=
ctx
.
GetParent
()
.
GetChild
(
0
)
.
(
antlr
.
ParseTree
)
.
GetText
()
var
targetType
=
parseTargetType
(
targetCtx
)
callee
:=
ctx
.
GetChild
(
0
)
.
(
antlr
.
ParseTree
)
.
GetText
()
startLine
:=
ctx
.
GetStart
()
.
GetLine
()
startLinePosition
:=
ctx
.
GetStart
()
.
GetColumn
()
stopLine
:=
ctx
.
GetStop
()
.
GetLine
()
stopLinePosition
:=
startLinePosition
+
len
(
callee
)
//typeType := ctx.GetChild(0).(antlr.ParseTree).TypeTypeOrVoid().GetText()
fullType
:=
warpTargetFullType
(
targetType
)
if
fullType
!=
""
{
jMethodCall
:=
&
JMethodCall
{
removeTarget
(
fullType
),
""
,
targetType
,
callee
,
startLine
,
startLinePosition
,
stopLine
,
stopLinePosition
}
methodCalls
=
append
(
methodCalls
,
*
jMethodCall
)
}
else
{
if
ctx
.
GetText
()
==
targetType
{
methodName
:=
ctx
.
IDENTIFIER
()
.
GetText
()
jMethodCall
:=
&
JMethodCall
{
currentPkg
,
""
,
currentClz
,
methodName
,
startLine
,
startLinePosition
,
stopLine
,
stopLinePosition
}
methodCalls
=
append
(
methodCalls
,
*
jMethodCall
)
}
}
}
func
(
s
*
BadSmellListener
)
EnterExpression
(
ctx
*
ExpressionContext
)
{
// lambda BlogPO::of
if
ctx
.
COLONCOLON
()
!=
nil
{
text
:=
ctx
.
Expression
(
0
)
.
GetText
()
methodName
:=
ctx
.
IDENTIFIER
()
.
GetText
()
targetType
:=
parseTargetType
(
text
)
fullType
:=
warpTargetFullType
(
targetType
)
startLine
:=
ctx
.
GetStart
()
.
GetLine
()
startLinePosition
:=
ctx
.
GetStart
()
.
GetColumn
()
stopLine
:=
ctx
.
GetStop
()
.
GetLine
()
stopLinePosition
:=
startLinePosition
+
len
(
text
)
jMethodCall
:=
&
JMethodCall
{
removeTarget
(
fullType
),
""
,
targetType
,
methodName
,
startLine
,
startLinePosition
,
stopLine
,
stopLinePosition
}
methodCalls
=
append
(
methodCalls
,
*
jMethodCall
)
}
}
func
(
s
*
BadSmellListener
)
appendClasses
(
classes
[]
string
)
{
clzs
=
classes
}
func
removeTarget
(
fullType
string
)
string
{
split
:=
strings
.
Split
(
fullType
,
"."
)
return
strings
.
Join
(
split
[
:
len
(
split
)
-
1
],
"."
)
}
func
parseTargetType
(
targetCtx
string
)
string
{
targetVar
:=
targetCtx
targetType
:=
targetVar
//TODO: update this reflect
typeOf
:=
reflect
.
TypeOf
(
targetCtx
)
.
String
()
if
strings
.
HasSuffix
(
typeOf
,
"MethodCallContext"
)
{
targetType
=
currentClz
;
}
else
{
fieldType
:=
fields
[
targetVar
]
formalType
:=
formalParameters
[
targetVar
]
localVarType
:=
localVars
[
targetVar
]
if
fieldType
!=
""
{
targetType
=
fieldType
}
else
if
formalType
!=
""
{
targetType
=
formalType
;
}
else
if
localVarType
!=
""
{
targetType
=
localVarType
;
}
}
return
targetType
}
func
warpTargetFullType
(
targetType
string
)
string
{
if
strings
.
EqualFold
(
currentClz
,
targetType
)
{
return
currentPkg
+
"."
+
targetType
}
for
index
:=
range
imports
{
imp
:=
imports
[
index
]
if
strings
.
HasSuffix
(
imp
,
targetType
)
{
return
imp
}
}
//maybe the same package
for
_
,
clz
:=
range
clzs
{
if
strings
.
HasSuffix
(
clz
,
"."
+
targetType
)
{
return
clz
}
}
//1. current package, 2. import by *
return
""
}
bs/bs.go
已删除
100644 → 0
浏览文件 @
61ac3a93
package
bs
import
(
"encoding/json"
"fmt"
.
"github.com/phodal/coca/adapter/models"
.
"github.com/phodal/coca/refactor/base/models"
.
"github.com/phodal/coca/utils"
)
var
nodes
[]
JMoveStruct
type
BadSmellApp
struct
{
}
var
depsFile
string
var
parsedDeps
[]
JClassNode
func
NewBadSmellApp
(
depPath
string
)
*
BadSmellApp
{
depsFile
=
depPath
return
&
BadSmellApp
{}
}
func
(
j
*
BadSmellApp
)
Start
()
{
file
:=
ReadFile
(
depsFile
)
if
file
==
nil
{
return
}
_
=
json
.
Unmarshal
(
file
,
&
parsedDeps
)
fmt
.
Println
(
parsedDeps
)
}
cmd/badsmell.go
浏览文件 @
320ca995
package
cmd
import
(
.
"github.com/phodal/coca/bs
"
"encoding/json
"
"github.com/spf13/cobra"
.
"github.com/phodal/coca/bs"
.
"github.com/phodal/coca/utils"
)
var
badsmellCmd
*
cobra
.
Command
=
&
cobra
.
Command
{
Use
:
"badsmell"
,
Short
:
"
badsmell recognized
"
,
Short
:
"
Bad Code Smell
"
,
Long
:
``
,
Run
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
depFile
:=
cmd
.
Flag
(
"dependence"
)
.
Value
.
String
()
importPath
:=
cmd
.
Flag
(
"path"
)
.
Value
.
String
()
if
importPath
!=
""
{
bsApp
:=
new
(
BadSmellApp
)
bsList
:=
bsApp
.
AnalysisPath
(
importPath
)
bsModel
,
_
:=
json
.
MarshalIndent
(
bsList
,
""
,
"
\t
"
)
if
depFile
!=
""
{
bsApp
:=
NewBadSmellApp
(
depFile
)
bsApp
.
Start
()
WriteToFile
(
"deps.json"
,
string
(
bsModel
))
}
},
}
...
...
@@ -22,5 +29,5 @@ var badsmellCmd *cobra.Command = &cobra.Command{
func
init
()
{
rootCmd
.
AddCommand
(
badsmellCmd
)
badsmellCmd
.
PersistentFlags
()
.
StringP
(
"
dependence"
,
"d"
,
""
,
"dependence path
"
)
badsmellCmd
.
PersistentFlags
()
.
StringP
(
"
path"
,
"p"
,
"Code Path"
,
"example -p src/main
"
)
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录