Skip to content

Commit f926a2c

Browse files
authored
Fix the Trie matching bug (#493)
Fixes #379
1 parent 8ddbf2c commit f926a2c

File tree

4 files changed

+117
-2
lines changed

4 files changed

+117
-2
lines changed

examples/issue379/filename.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
a = ''
2+
# equals to 'test'
3+
b = 'test'''
4+
5+
# comment
6+
for i in range(10):
7+
print(i)

processor/structs.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,20 @@ func (root *Trie) Match(token []byte) (int, int, []byte) {
183183
var c byte
184184

185185
node = root
186+
var prevClosedNode *Trie
187+
var prevClosedDepth int
186188
for depth, c = range token {
187189
if node.Table[c] == nil {
188-
return node.Type, depth, node.Close
190+
break
189191
}
190192
node = node.Table[c]
193+
if len(node.Close) > 0 {
194+
prevClosedNode = node
195+
prevClosedDepth = depth
196+
}
197+
}
198+
if len(node.Close) == 0 && prevClosedNode != nil {
199+
return prevClosedNode.Type, prevClosedDepth, prevClosedNode.Close
191200
}
192201
return node.Type, depth, node.Close
193202
}

processor/structs_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package processor
44

55
import (
6+
"slices"
67
"testing"
78
)
89

@@ -30,3 +31,66 @@ func TestCheckDuplicates(t *testing.T) {
3031
t.Error("Expected no match")
3132
}
3233
}
34+
35+
func TestMatch(t *testing.T) {
36+
trie := &Trie{}
37+
trie.InsertClose(TString, []byte("'"), []byte("'"))
38+
trie.InsertClose(TString, []byte("'''"), []byte("'''"))
39+
40+
testCases := []struct {
41+
token []byte
42+
expectType int
43+
expectDepth int
44+
expectClosed []byte
45+
}{
46+
{
47+
token: []byte("'"),
48+
expectType: TString,
49+
expectDepth: 0,
50+
expectClosed: []byte("'"),
51+
},
52+
{
53+
token: []byte("-"),
54+
expectType: 0,
55+
expectDepth: 0,
56+
expectClosed: []byte{},
57+
},
58+
{
59+
token: []byte("'-"),
60+
expectType: TString,
61+
expectDepth: 1,
62+
expectClosed: []byte("'"),
63+
},
64+
{
65+
token: []byte("''"),
66+
expectType: TString,
67+
expectDepth: 0,
68+
expectClosed: []byte("'"),
69+
},
70+
{
71+
token: []byte("'''"),
72+
expectType: 1,
73+
expectDepth: 2,
74+
expectClosed: []byte("'''"),
75+
},
76+
{
77+
token: []byte("'''a'''"),
78+
expectType: TString,
79+
expectDepth: 3,
80+
expectClosed: []byte("'''"),
81+
},
82+
}
83+
84+
for _, tc := range testCases {
85+
typ, depth, closed := trie.Match(tc.token)
86+
if typ != tc.expectType {
87+
t.Errorf("\"%v\" matched wrong type, want: %v, got: %v", string(tc.token), tc.expectType, typ)
88+
}
89+
if depth != tc.expectDepth {
90+
t.Errorf("\"%v\" matched wrong depth, want: %v, got: %v", string(tc.token), tc.expectDepth, depth)
91+
}
92+
if !slices.Equal(tc.expectClosed, closed) {
93+
t.Errorf("\"%v\" matched wrong closed, want: %v, got: %v", string(tc.token), tc.expectClosed, closed)
94+
}
95+
}
96+
}

test-all.sh

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -935,7 +935,7 @@ done
935935
a=$(./scc "examples/issue345/" -f csv | sed -n '2 p')
936936
b="C++,4,3,1,0,0,76,1,0"
937937
if [ "$a" == "$b" ]; then
938-
echo -e "{GREEN}PASSED string termination check"
938+
echo -e "${GREEN}PASSED string termination check"
939939
else
940940
echo -e "$a"
941941
echo -e "${RED}======================================================="
@@ -944,6 +944,41 @@ else
944944
exit
945945
fi
946946

947+
# Regression issue https://github.com/boyter/scc/issues/379
948+
Issue379Line=$(./scc -f csv "examples/issue379/" | grep 'Python' | cut -d ',' -f 2)
949+
Issue379Code=$(./scc -f csv "examples/issue379/" | grep 'Python' | cut -d ',' -f 3)
950+
Issue379Comments=$(./scc -f csv "examples/issue379/" | grep 'Python' | cut -d ',' -f 4)
951+
Issue379Blanks=$(./scc -f csv "examples/issue379/" | grep 'Python' | cut -d ',' -f 5)
952+
Issue379Complexity=$(./scc -f csv "examples/issue379/" | grep 'Python' | cut -d ',' -f 6)
953+
if [ $Issue379Line -ne 7 ] ; then
954+
echo -e "${RED}======================================================="
955+
echo -e "FAILED Issue379 line counting"
956+
echo -e "=======================================================${NC}"
957+
exit
958+
elif [ $Issue379Code -ne 4 ] ; then
959+
echo -e "${RED}======================================================="
960+
echo -e "FAILED Issue379 code counting"
961+
echo -e "=======================================================${NC}"
962+
exit
963+
elif [ $Issue379Comments -ne 2 ] ; then
964+
echo -e "${RED}======================================================="
965+
echo -e "FAILED Issue379 comments counting"
966+
echo -e "=======================================================${NC}"
967+
exit
968+
elif [ $Issue379Blanks -ne 1 ] ; then
969+
echo -e "${RED}======================================================="
970+
echo -e "FAILED Issue379 blanks counting"
971+
echo -e "=======================================================${NC}"
972+
exit
973+
elif [ $Issue379Complexity -ne 1 ] ; then
974+
echo -e "${RED}======================================================="
975+
echo -e "FAILED Issue379 complexity counting"
976+
echo -e "=======================================================${NC}"
977+
exit
978+
else
979+
echo -e "${GREEN}PASSED Issue379 Regression Check"
980+
fi
981+
947982
# Extra case for longer languages that are normally truncated
948983
for i in 'CloudFormation (YAM' 'CloudFormation (JSO'
949984
do

0 commit comments

Comments
 (0)