Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
镜像
koalaman
ShellCheck
提交
2f0ae44d
S
ShellCheck
项目概览
镜像
/
koalaman
/
ShellCheck
上一次同步 大约 1 年
通知
43
Star
0
Fork
1
代码
文件
提交
分支
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,发现更多精彩内容 >>
提交
2f0ae44d
编写于
4月 16, 2016
作者:
V
Vidar Holen
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix parsing of here documents
上级
51d8caf2
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
122 addition
and
40 deletion
+122
-40
ShellCheck/AST.hs
ShellCheck/AST.hs
+1
-1
ShellCheck/Parser.hs
ShellCheck/Parser.hs
+121
-39
未找到文件。
ShellCheck/AST.hs
浏览文件 @
2f0ae44d
...
...
@@ -166,7 +166,7 @@ analyze f g i =
dll
l
m
v
=
do
x
<-
roundAll
l
y
<-
roundAll
m
return
$
v
x
m
return
$
v
x
y
d1
t
v
=
do
x
<-
round
t
return
$
v
x
...
...
ShellCheck/Parser.hs
浏览文件 @
2f0ae44d
...
...
@@ -52,20 +52,24 @@ type SCParser m v = ParsecT String UserState (SCBase m) v
backslash
::
Monad
m
=>
SCParser
m
Char
backslash
=
char
'
\\
'
linefeed
=
optional
carriageReturn
>>
char
'
\n
'
linefeed
::
Monad
m
=>
SCParser
m
Char
linefeed
=
do
optional
carriageReturn
c
<-
char
'
\n
'
readPendingHereDocs
return
c
singleQuote
=
char
'
\'
'
<|>
unicodeSingleQuote
doubleQuote
=
char
'"'
<|>
unicodeDoubleQuote
variableStart
=
upper
<|>
lower
<|>
oneOf
"_"
variableChars
=
upper
<|>
lower
<|>
digit
<|>
oneOf
"_"
functionChars
=
variableChars
<|>
oneOf
":+-.?"
specialVariable
=
oneOf
"@*#?-$!"
tokenDelimiter
=
oneOf
"&|;<>
\t\n\r
"
<|>
almostSpace
quotableChars
=
"|&;<>()
\\
'
\t\n\r\xA0
"
++
doubleQuotableChars
quotable
=
almostSpace
<|>
unicodeDoubleQuote
<|>
oneOf
quotableChars
bracedQuotable
=
oneOf
"}
\"
$`'"
doubleQuotableChars
=
"
\"
$`"
++
unicodeDoubleQuoteChars
doubleQuotable
=
unicodeDoubleQuote
<|>
oneOf
doubleQuotableChars
whitespace
=
oneOf
"
\t
\n
"
<|>
carriageReturn
<|>
almostSpace
whitespace
=
oneOf
"
\t
"
<|>
carriageReturn
<|>
almostSpace
<|>
linefeed
linewhitespace
=
oneOf
"
\t
"
<|>
almostSpace
suspectCharAfterQuotes
=
variableChars
<|>
char
'%'
...
...
@@ -138,15 +142,24 @@ data Context =
|
ContextSource
String
deriving
(
Show
)
data
HereDocContext
=
HereDocPending
Token
-- on linefeed, read this T_HereDoc
|
HereDocBoundary
-- but don't consider heredocs before this
deriving
(
Show
)
data
UserState
=
UserState
{
lastId
::
Id
,
positionMap
::
Map
.
Map
Id
SourcePos
,
parseNotes
::
[
ParseNote
]
parseNotes
::
[
ParseNote
],
hereDocMap
::
Map
.
Map
Id
[
Token
],
pendingHereDocs
::
[
HereDocContext
]
}
initialUserState
=
UserState
{
lastId
=
Id
$
-
1
,
positionMap
=
Map
.
empty
,
parseNotes
=
[]
parseNotes
=
[]
,
hereDocMap
=
Map
.
empty
,
pendingHereDocs
=
[]
}
codeForParseNote
(
ParseNote
_
_
code
_
)
=
code
...
...
@@ -155,7 +168,6 @@ noteToParseNote map (Note id severity code message) =
where
pos
=
fromJust
$
Map
.
lookup
id
map
getLastId
=
lastId
<$>
getState
getNextIdAt
sourcepos
=
do
...
...
@@ -173,6 +185,58 @@ getNextId = do
pos
<-
getPosition
getNextIdAt
pos
addToHereDocMap
id
list
=
do
state
<-
getState
let
map
=
hereDocMap
state
putState
$
state
{
hereDocMap
=
Map
.
insert
id
list
map
}
withHereDocBoundary
p
=
do
pushBoundary
do
v
<-
p
popBoundary
return
v
<|>
do
popBoundary
fail
""
where
pushBoundary
=
do
state
<-
getState
let
docs
=
pendingHereDocs
state
putState
$
state
{
pendingHereDocs
=
HereDocBoundary
:
docs
}
popBoundary
=
do
state
<-
getState
let
docs
=
tail
$
dropWhile
(
not
.
isHereDocBoundary
)
$
pendingHereDocs
state
putState
$
state
{
pendingHereDocs
=
docs
}
addPendingHereDoc
t
=
do
state
<-
getState
let
docs
=
pendingHereDocs
state
putState
$
state
{
pendingHereDocs
=
HereDocPending
t
:
docs
}
popPendingHereDocs
=
do
state
<-
getState
let
(
pending
,
boundary
)
=
break
isHereDocBoundary
$
pendingHereDocs
state
putState
$
state
{
pendingHereDocs
=
boundary
}
return
.
map
extract
.
reverse
$
pendingHereDocs
state
where
extract
(
HereDocPending
t
)
=
t
isHereDocBoundary
x
=
case
x
of
HereDocBoundary
->
True
otherwise
->
False
getMap
=
positionMap
<$>
getState
getParseNotes
=
parseNotes
<$>
getState
...
...
@@ -1384,14 +1448,17 @@ readDollarLonely = do
n
<-
lookAhead
(
anyChar
<|>
(
eof
>>
return
'_'
))
return
$
T_Literal
id
"$"
prop_readHereDoc
=
isOk
readHereDoc
"<< foo
\n
lol
\n
cow
\n
foo"
prop_readHereDoc2
=
isWarning
readHereDoc
"<<- EOF
\n
cow
\n
EOF"
prop_readHereDoc3
=
isOk
readHereDoc
"<< foo
\n
$
\"\n
foo"
prop_readHereDoc4
=
isOk
readHereDoc
"<< foo
\n
`
\n
foo"
prop_readHereDoc5
=
isOk
readHereDoc
"<<- !foo
\n
bar
\n
!foo"
prop_readHereDoc6
=
isOk
readHereDoc
"<< foo
\\
bar
\n
cow
\n
foo bar"
prop_readHereDoc7
=
isOk
readHereDoc
"<< foo
\n\\
$(f ())
\n
foo"
prop_readHereDoc8
=
isOk
readHereDoc
"<<foo>>bar
\n
etc
\n
foo"
prop_readHereDoc
=
isOk
readScript
"cat << foo
\n
lol
\n
cow
\n
foo"
prop_readHereDoc2
=
isWarning
readScript
"cat <<- EOF
\n
cow
\n
EOF"
prop_readHereDoc3
=
isOk
readScript
"cat << foo
\n
$
\"\n
foo"
prop_readHereDoc4
=
isOk
readScript
"cat << foo
\n
`
\n
foo"
prop_readHereDoc5
=
isOk
readScript
"cat <<- !foo
\n
bar
\n
!foo"
prop_readHereDoc6
=
isOk
readScript
"cat << foo
\\
bar
\n
cow
\n
foo bar"
prop_readHereDoc7
=
isOk
readScript
"cat << foo
\n\\
$(f ())
\n
foo"
prop_readHereDoc8
=
isOk
readScript
"cat <<foo>>bar
\n
etc
\n
foo"
prop_readHereDoc9
=
isOk
readScript
"if true; then cat << foo; fi
\n
bar
\n
foo
\n
"
prop_readHereDoc10
=
isOk
readScript
"if true; then cat << foo << bar; fi
\n
foo
\n
bar
\n
"
prop_readHereDoc11
=
isOk
readScript
"cat << foo $(
\n
foo
\n
)lol
\n
foo
\n
"
readHereDoc
=
called
"here document"
$
do
fid
<-
getNextId
pos
<-
getPosition
...
...
@@ -1408,24 +1475,11 @@ readHereDoc = called "here document" $ do
liftM
(
\
x
->
(
Quoted
,
stripLiteral
x
))
readDoubleQuotedLiteral
<|>
liftM
(
\
x
->
(
Quoted
,
x
))
readSingleQuotedLiteral
<|>
(
readToken
>>=
(
\
x
->
return
(
Unquoted
,
x
)))
spacing
startPos
<-
getPosition
hereData
<-
anyChar
`
reluctantlyTill
`
do
linefeed
spacing
string
endToken
disregard
linefeed
<|>
eof
do
linefeed
spaces
<-
spacing
verifyHereDoc
dashed
quoted
spaces
hereData
string
endToken
parsedData
<-
parseHereData
quoted
startPos
hereData
return
$
T_FdRedirect
fid
""
$
T_HereDoc
hid
dashed
quoted
endToken
parsedData
`
attempting
`
(
eof
>>
debugHereDoc
tokenPosition
endToken
hereData
)
-- add empty tokens for now, read the rest in readPendingHereDocs
let
doc
=
T_HereDoc
hid
dashed
quoted
endToken
[]
addPendingHereDoc
doc
return
$
T_FdRedirect
fid
""
doc
where
stripLiteral
(
T_Literal
_
x
)
=
x
stripLiteral
(
T_SingleQuoted
_
x
)
=
x
...
...
@@ -1440,6 +1494,27 @@ readHereDoc = called "here document" $ do
c
<-
anyChar
return
[
c
]
readPendingHereDocs
=
do
docs
<-
popPendingHereDocs
mapM_
readDoc
docs
where
readDoc
(
T_HereDoc
id
dashed
quoted
endToken
_
)
=
do
pos
<-
getPosition
hereData
<-
anyChar
`
reluctantlyTill
`
do
spacing
string
endToken
disregard
(
char
'
\n
'
)
<|>
eof
do
spaces
<-
spacing
verifyHereDoc
dashed
quoted
spaces
hereData
string
endToken
parsedData
<-
parseHereData
quoted
pos
hereData
list
<-
parseHereData
quoted
pos
hereData
addToHereDocMap
id
list
`
attempting
`
(
eof
>>
debugHereDoc
pos
endToken
hereData
)
parseHereData
Quoted
startPos
hereData
=
do
id
<-
getNextIdAt
startPos
return
[
T_Literal
id
hereData
]
...
...
@@ -1524,7 +1599,7 @@ readHereString = called "here string" $ do
word
<-
readNormalWord
return
$
T_FdRedirect
id
""
$
T_HereString
id2
word
readNewlineList
=
many1
((
newline
<|>
carriageReturn
)
`
thenSkip
`
spacing
)
readNewlineList
=
many1
((
linefeed
<|>
carriageReturn
)
`
thenSkip
`
spacing
)
readLineBreak
=
optional
readNewlineList
prop_readSeparator1
=
isWarning
readScript
"a &; b"
...
...
@@ -2475,9 +2550,8 @@ parsesCleanly parser string = runIdentity $ do
parseWithNotes
parser
=
do
item
<-
parser
map
<-
getMap
parseNotes
<-
getParseNotes
return
(
item
,
map
,
nub
.
sortNotes
$
parseNotes
)
state
<-
getState
return
(
item
,
state
)
compareNotes
(
ParseNote
pos1
level1
_
s1
)
(
ParseNote
pos2
level2
_
s2
)
=
compare
(
pos1
,
level1
)
(
pos2
,
level2
)
sortNotes
=
sortBy
compareNotes
...
...
@@ -2517,11 +2591,12 @@ system = lift . lift . lift
parseShell
sys
name
contents
=
do
(
result
,
state
)
<-
runParser
sys
(
parseWithNotes
readScript
)
name
contents
case
result
of
Right
(
script
,
tokenMap
,
notes
)
->
Right
(
script
,
userstate
)
->
return
ParseResult
{
prComments
=
map
toPositionedComment
$
nub
$
notes
++
parseProblems
state
,
prTokenPositions
=
Map
.
map
posToPos
tokenMap
,
prRoot
=
Just
script
prComments
=
map
toPositionedComment
$
nub
$
parseNotes
userstate
++
parseProblems
state
,
prTokenPositions
=
Map
.
map
posToPos
(
positionMap
userstate
),
prRoot
=
Just
$
reattachHereDocs
script
(
hereDocMap
userstate
)
}
Left
err
->
return
ParseResult
{
...
...
@@ -2542,6 +2617,13 @@ parseShell sys name contents = do
second
(
ContextName
pos
str
)
=
ParseNote
pos
InfoC
1009
$
"The mentioned parser error was in this "
++
str
++
"."
reattachHereDocs
root
map
=
doTransform
f
root
where
f
t
@
(
T_HereDoc
id
dash
quote
string
[]
)
=
fromMaybe
t
$
do
list
<-
Map
.
lookup
id
map
return
$
T_HereDoc
id
dash
quote
string
list
f
t
=
t
toPositionedComment
::
ParseNote
->
PositionedComment
toPositionedComment
(
ParseNote
pos
severity
code
message
)
=
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录