Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Annlix
ShellCheck
提交
97e886e6
S
ShellCheck
项目概览
Annlix
/
ShellCheck
与 Fork 源项目一致
Fork自
镜像 / koalaman / ShellCheck
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
ShellCheck
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
97e886e6
编写于
11月 08, 2012
作者:
V
Vidar Holen
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Added more [[]]-related checks
上级
977cf427
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
59 addition
and
26 deletion
+59
-26
ShellCheck/Analytics.hs
ShellCheck/Analytics.hs
+28
-0
ShellCheck/Parser.hs
ShellCheck/Parser.hs
+29
-25
badcase/singlebracketcompare
badcase/singlebracketcompare
+1
-0
shellcheck.hs
shellcheck.hs
+1
-1
未找到文件。
ShellCheck/Analytics.hs
浏览文件 @
97e886e6
...
...
@@ -31,6 +31,8 @@ basicChecks = [
,
checkStderrRedirect
,
checkMissingPositionalQuotes
,
checkSingleQuotedVariables
,
checkUnquotedZN
,
checkNumberComparisons
]
modifyMap
=
modify
...
...
@@ -197,6 +199,32 @@ checkSingleQuotedVariables _ = return ()
checkSingleQuotedVariablesRe
=
mkRegex
"(
\\
$[0-9a-zA-Z_]+)"
prop_checkUnquotedZN
=
verify
checkUnquotedZN
"if [ -z $foo ]; then echo cow; fi"
prop_checkUnquotedZN2
=
verify
checkUnquotedZN
"[ -n $cow ]"
prop_checkUnquotedZN3
=
verifyNot
checkUnquotedZN
"[[ -z $foo ]] && echo cow"
checkUnquotedZN
(
T_Condition
_
SingleBracket
(
TC_Unary
_
SingleBracket
op
(
T_NormalWord
id
[
t
])))
|
(
op
==
"-z"
||
op
==
"-n"
)
&&
willSplit
t
=
addNoteFor
id
$
Note
ErrorC
"Always true because you failed to quote. Use [[ ]] instead."
checkUnquotedZN
_
=
return
()
prop_checkNumberComparisons1
=
verify
checkNumberComparisons
"[[ $foo < 3 ]]"
prop_checkNumberComparisons2
=
verify
checkNumberComparisons
"[[ 0 >= $(cmd) ]]"
prop_checkNumberComparisons3
=
verifyNot
checkNumberComparisons
"[[ $foo ]] > 3"
prop_checkNumberComparisons4
=
verify
checkNumberComparisons
"[ $foo > $bar ]"
prop_checkNumberComparisons5
=
verify
checkNumberComparisons
"until [ $n <= $z ]; do echo foo; done"
checkNumberComparisons
(
TC_Binary
id
typ
op
lhs
rhs
)
|
op
`
elem
`
[
"<"
,
">"
,
"<="
,
">="
]
=
do
when
(
isNum
lhs
||
isNum
rhs
)
$
addNoteFor
id
$
Note
ErrorC
$
"
\"
"
++
op
++
"
\"
is for string comparisons. Use "
++
(
eqv
op
)
when
(
typ
==
SingleBracket
)
$
addNoteFor
id
$
Note
ErrorC
$
"Can't use "
++
op
++
" in [ ]. Use [[ ]]."
where
isNum
t
=
case
deadSimple
t
of
[
v
]
->
all
isDigit
v
_
->
False
eqv
"<"
=
"-lt"
eqv
">"
=
"-gt"
eqv
"<="
=
"-le"
eqv
">="
=
"-ge"
eqv
_
=
"the numerical equivalent"
checkNumberComparisons
_
=
return
()
allModifiedVariables
t
=
snd
$
runState
(
doAnalysis
(
\
x
->
modify
$
(
++
)
(
getModifiedVariables
t
))
t
)
[]
--- Subshell detection
...
...
ShellCheck/Parser.hs
浏览文件 @
97e886e6
{-# LANGUAGE NoMonomorphismRestriction #-}
module
ShellCheck.Parser
(
Token
(
..
),
Id
(
..
),
Note
(
..
),
Severity
(
..
),
parseShell
,
ParseResult
(
..
),
ParseNote
(
..
),
notesFromMap
,
Metadata
(
..
),
doAnalysis
,
doStackAnalysis
,
doTransform
,
sortNotes
)
where
module
ShellCheck.Parser
(
Token
(
..
),
ConditionType
(
..
),
Id
(
..
),
Note
(
..
),
Severity
(
..
),
parseShell
,
ParseResult
(
..
),
ParseNote
(
..
),
notesFromMap
,
Metadata
(
..
),
doAnalysis
,
doStackAnalysis
,
doTransform
,
sortNotes
)
where
import
Text.Parsec
import
Debug.Trace
...
...
@@ -153,14 +153,15 @@ readConditionContents single = do
parseProblemAt
pos
WarningC
"To check a command, skip [] and just do 'if foo | grep bar; then'."
)
where
typ
=
if
single
then
SingleBracket
else
DoubleBracket
readCondBinaryOp
=
try
$
do
op
<-
choice
$
(
map
tryOp
[
"-nt"
,
"-ot"
,
"-ef"
,
"="
,
"=="
,
"!="
,
"<
"
,
">"
,
"-eq"
,
"-ne"
,
"-lt"
,
"-le"
,
"-gt"
,
"-ge"
,
"=~
"
])
op
<-
choice
$
(
map
tryOp
[
"-nt"
,
"-ot"
,
"-ef"
,
"="
,
"=="
,
"!="
,
"<
="
,
">="
,
"-eq"
,
"-ne"
,
"-lt"
,
"-le"
,
"-gt"
,
"-ge"
,
"=~"
,
">"
,
"<
"
])
hardCondSpacing
return
op
where
tryOp
s
=
try
$
do
id
<-
getNextId
string
s
return
$
TC_Binary
id
s
return
$
TC_Binary
id
typ
s
readCondUnaryExp
=
do
op
<-
readCondUnaryOp
...
...
@@ -181,7 +182,7 @@ readConditionContents single = do
where
tryOp
s
=
try
$
do
id
<-
getNextId
string
s
return
$
TC_Unary
id
s
return
$
TC_Unary
id
typ
s
readCondWord
=
do
notFollowedBy
(
try
(
spacing
>>
(
string
"]"
)))
...
...
@@ -205,7 +206,8 @@ readConditionContents single = do
when
(
single
&&
x
==
"&&"
)
$
addNoteFor
id
$
Note
ErrorC
"You can't use && inside [..]. Use [[..]] instead."
when
(
not
single
&&
x
==
"-a"
)
$
addNoteFor
id
$
Note
ErrorC
"In [[..]], use && instead of -a"
softCondSpacing
return
$
TC_And
id
x
return
$
TC_And
id
typ
x
readCondOrOp
=
do
id
<-
getNextId
...
...
@@ -213,7 +215,7 @@ readConditionContents single = do
when
(
single
&&
x
==
"||"
)
$
addNoteFor
id
$
Note
ErrorC
"You can't use || inside [..]. Use [[..]] instead."
when
(
not
single
&&
x
==
"-o"
)
$
addNoteFor
id
$
Note
ErrorC
"In [[..]], use && instead of -o"
softCondSpacing
return
$
TC_Or
id
x
return
$
TC_Or
id
typ
x
readCondNoaryOrBinary
=
do
id
<-
getNextId
...
...
@@ -229,7 +231,7 @@ readConditionContents single = do
op
<-
readCondBinaryOp
y
<-
readCondWord
<|>
(
(
parseProblemAt
pos
ErrorC
$
"Expected another argument for this operator"
)
>>
mzero
)
return
(
x
`
op
`
y
)
)
<|>
(
return
$
TC_Noary
id
x
)
)
<|>
(
return
$
TC_Noary
id
typ
x
)
readCondGroup
=
do
id
<-
getNextId
...
...
@@ -242,7 +244,7 @@ readConditionContents single = do
rparen
<-
string
")"
<|>
string
"
\\
)"
when
(
single
&&
rparen
==
")"
)
$
parseProblemAt
pos
ErrorC
"In [..] you have to escape (). Use [[..]] instead."
when
(
isEscaped
lparen
`
xor
`
isEscaped
rparen
)
$
parseProblemAt
pos
ErrorC
"Did you just escape one half of () but not the other?"
return
$
TC_Group
id
x
return
$
TC_Group
id
typ
x
where
isEscaped
(
'
\\
'
:
_
)
=
True
isEscaped
_
=
False
...
...
@@ -254,7 +256,7 @@ readConditionContents single = do
char
'!'
softCondSpacing
expr
<-
readCondExpr
return
$
TC_Not
id
expr
return
$
TC_Not
id
typ
expr
readCondExpr
=
readCondGroup
<|>
readCondUnaryExp
<|>
readCondNoaryOrBinary
...
...
@@ -278,7 +280,7 @@ readCondition = do
close
<-
(
try
$
string
"]]"
)
<|>
(
string
"]"
)
when
(
open
==
"[["
&&
close
/=
"]]"
)
$
parseProblemAt
cpos
ErrorC
"Did you mean ]] ?"
when
(
open
==
"["
&&
close
/=
"]"
)
$
parseProblemAt
opos
ErrorC
"Did you mean [[ ?"
return
$
T_Condition
id
condition
return
$
T_Condition
id
(
if
single
then
SingleBracket
else
DoubleBracket
)
condition
hardCondSpacing
=
condSpacingMsg
False
"You need a space here"
...
...
@@ -290,9 +292,11 @@ condSpacingMsg soft msg = do
-- Horrifying AST
data
Token
=
T_AND_IF
Id
|
T_OR_IF
Id
|
T_DSEMI
Id
|
T_Semi
Id
|
T_DLESS
Id
|
T_DGREAT
Id
|
T_LESSAND
Id
|
T_GREATAND
Id
|
T_LESSGREAT
Id
|
T_DLESSDASH
Id
|
T_CLOBBER
Id
|
T_If
Id
|
T_Then
Id
|
T_Else
Id
|
T_Elif
Id
|
T_Fi
Id
|
T_Do
Id
|
T_Done
Id
|
T_Case
Id
|
T_Esac
Id
|
T_While
Id
|
T_Until
Id
|
T_For
Id
|
T_Lbrace
Id
|
T_Rbrace
Id
|
T_Lparen
Id
|
T_Rparen
Id
|
T_Bang
Id
|
T_In
Id
|
T_NEWLINE
Id
|
T_EOF
Id
|
T_Less
Id
|
T_Greater
Id
|
T_SingleQuoted
Id
String
|
T_Literal
Id
String
|
T_NormalWord
Id
[
Token
]
|
T_DoubleQuoted
Id
[
Token
]
|
T_DollarExpansion
Id
[
Token
]
|
T_DollarBraced
Id
String
|
T_DollarArithmetic
Id
String
|
T_BraceExpansion
Id
String
|
T_IoFile
Id
Token
Token
|
T_HereDoc
Id
Bool
Bool
String
|
T_HereString
Id
Token
|
T_FdRedirect
Id
String
Token
|
T_Assignment
Id
String
Token
|
T_Array
Id
[
Token
]
|
T_Redirecting
Id
[
Token
]
Token
|
T_SimpleCommand
Id
[
Token
]
[
Token
]
|
T_Pipeline
Id
[
Token
]
|
T_Banged
Id
Token
|
T_AndIf
Id
(
Token
)
(
Token
)
|
T_OrIf
Id
(
Token
)
(
Token
)
|
T_Backgrounded
Id
Token
|
T_IfExpression
Id
[([
Token
],[
Token
])]
[
Token
]
|
T_Subshell
Id
[
Token
]
|
T_BraceGroup
Id
[
Token
]
|
T_WhileExpression
Id
[
Token
]
[
Token
]
|
T_UntilExpression
Id
[
Token
]
[
Token
]
|
T_ForIn
Id
String
[
Token
]
[
Token
]
|
T_CaseExpression
Id
Token
[([
Token
],[
Token
])]
|
T_Function
Id
String
Token
|
T_Arithmetic
Id
String
|
T_Script
Id
[
Token
]
|
T_Condition
Id
Token
|
TC_And
Id
String
Token
Token
|
TC_Or
Id
String
Token
Token
|
TC_Not
Id
Token
|
TC_Group
Id
Token
|
TC_Binary
Id
String
Token
Token
|
TC_Unary
Id
String
Token
|
TC_Noary
Id
Token
T_Condition
Id
ConditionType
Token
|
TC_And
Id
ConditionType
String
Token
Token
|
TC_Or
Id
ConditionType
String
Token
Token
|
TC_Not
Id
ConditionType
Token
|
TC_Group
Id
ConditionType
Token
|
TC_Binary
Id
ConditionType
String
Token
Token
|
TC_Unary
Id
ConditionType
String
Token
|
TC_Noary
Id
ConditionType
Token
deriving
(
Show
)
data
ConditionType
=
DoubleBracket
|
SingleBracket
deriving
(
Show
,
Eq
)
analyzeScopes
f
g
i
=
mapM
(
analyze
f
g
i
)
analyze
f
g
i
s
@
(
T_NormalWord
id
list
)
=
do
...
...
@@ -457,50 +461,50 @@ analyze f g i s@(T_Function id name body) = do
g
s
return
.
i
$
T_Function
id
name
a
analyze
f
g
i
s
@
(
T_Condition
id
token
)
=
do
analyze
f
g
i
s
@
(
T_Condition
id
t
yp
t
oken
)
=
do
f
s
a
<-
analyze
f
g
i
token
g
s
return
.
i
$
T_Condition
id
a
return
.
i
$
T_Condition
id
typ
a
analyze
f
g
i
s
@
(
TC_And
id
str
t1
t2
)
=
do
analyze
f
g
i
s
@
(
TC_And
id
typ
str
t1
t2
)
=
do
f
s
a
<-
analyze
f
g
i
t1
b
<-
analyze
f
g
i
t2
g
s
return
.
i
$
TC_And
id
str
a
b
return
.
i
$
TC_And
id
typ
str
a
b
analyze
f
g
i
s
@
(
TC_Or
id
str
t1
t2
)
=
do
analyze
f
g
i
s
@
(
TC_Or
id
typ
str
t1
t2
)
=
do
f
s
a
<-
analyze
f
g
i
t1
b
<-
analyze
f
g
i
t2
g
s
return
.
i
$
TC_Or
id
str
a
b
return
.
i
$
TC_Or
id
typ
str
a
b
analyze
f
g
i
s
@
(
TC_Group
id
token
)
=
do
analyze
f
g
i
s
@
(
TC_Group
id
t
yp
t
oken
)
=
do
f
s
a
<-
analyze
f
g
i
token
g
s
return
.
i
$
TC_Group
id
a
return
.
i
$
TC_Group
id
typ
a
analyze
f
g
i
s
@
(
TC_Binary
id
op
lhs
rhs
)
=
do
analyze
f
g
i
s
@
(
TC_Binary
id
typ
op
lhs
rhs
)
=
do
f
s
a
<-
analyze
f
g
i
lhs
b
<-
analyze
f
g
i
rhs
g
s
return
.
i
$
TC_Binary
id
op
a
b
return
.
i
$
TC_Binary
id
typ
op
a
b
analyze
f
g
i
s
@
(
TC_Unary
id
op
token
)
=
do
analyze
f
g
i
s
@
(
TC_Unary
id
typ
op
token
)
=
do
f
s
a
<-
analyze
f
g
i
token
g
s
return
.
i
$
TC_Unary
id
op
a
return
.
i
$
TC_Unary
id
typ
op
a
analyze
f
g
i
s
@
(
TC_Noary
id
token
)
=
do
analyze
f
g
i
s
@
(
TC_Noary
id
t
yp
t
oken
)
=
do
f
s
a
<-
analyze
f
g
i
token
g
s
return
.
i
$
TC_Noary
id
a
return
.
i
$
TC_Noary
id
typ
a
analyze
f
g
i
t
=
do
f
t
...
...
badcase/singlebracketcompare
0 → 100644
浏览文件 @
97e886e6
until [ $var > $foo ]; do var=$(cow); done
shellcheck.hs
浏览文件 @
97e886e6
...
...
@@ -13,7 +13,7 @@ ansi n = "\x1B[" ++ (show n) ++ "m"
colorForLevel
"error"
=
31
-- red
colorForLevel
"warning"
=
33
-- yellow
colorForLevel
"info"
=
3
3
-- yellow
colorForLevel
"info"
=
3
2
-- green
colorForLevel
"style"
=
32
-- green
colorForLevel
"message"
=
1
-- bold
colorForLevel
"source"
=
0
-- none
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录