Repository: terryyin/lizard

Issue:
lizard gets confused by C++ thousands seperator in hex and binary numbers
This is essentially the same bug as #352 except that it applies to using a binary base or hexadecimal base.

i.e. Replace `100'000` in the #352 example with `0b0000'1100` or `0x1234'5678`

Hints from issue comments:

Solution patch:
diff --git a/lizard_languages/code_reader.py b/lizard_languages/code_reader.py
index 9e12658..e8d7d98 100644
--- a/lizard_languages/code_reader.py
+++ b/lizard_languages/code_reader.py
@@ -127,6 +127,8 @@ class CodeReader:
                 r"\/\*.*?\*\/" +
                 add +
                 r"|(?:\d+\')+\d+" +
+                r"|0x(?:[0-9A-Fa-f]+\')+[0-9A-Fa-f]+" +
+                r"|0b(?:[01]+\')+[01]+" +
                 r"|\w+" +
                 r"|\"(?:\\.|[^\"\\])*\"" +
                 r"|\'(?:\\.|[^\'\\])*?\'" +
diff --git a/lizard_languages/golike.py b/lizard_languages/golike.py
index caa1583..a131460 100644
--- a/lizard_languages/golike.py
+++ b/lizard_languages/golike.py
@@ -13,11 +13,32 @@ class GoLikeStates(CodeStateMachine):  # pylint: disable=R0903
         if token == self.FUNC_KEYWORD:
             self._state = self._function_name
             self.context.push_new_function('')
+        elif token == 'type':
+            self._state = self._type_definition
         elif token in '{':
             self.sub_state(self.statemachine_clone())
         elif token in '}':
             self.statemachine_return()
 
+    def _type_definition(self, token):
+        self._state = self._after_type_name
+
+    def _after_type_name(self, token):
+        if token == 'struct':
+            self._state = self._struct_definition
+        elif token == 'interface':
+            self._state = self._interface_definition
+        else:
+            self._state = self._state_global
+
+    @CodeStateMachine.read_inside_brackets_then("{}", "_state_global")
+    def _struct_definition(self, tokens):
+        pass
+
+    @CodeStateMachine.read_inside_brackets_then("{}", "_state_global")
+    def _interface_definition(self, tokens):
+        pass
+
     def _function_name(self, token):
         if token != '`':
             if token == '(':


Test patch:
diff --git a/test/test_languages/testCAndCPP.py b/test/test_languages/testCAndCPP.py
index 17646ce..b04b901 100644
--- a/test/test_languages/testCAndCPP.py
+++ b/test/test_languages/testCAndCPP.py
@@ -100,6 +100,20 @@ class Test_c_cpp_lizard(unittest.TestCase):
         self.assertEqual(1, len(result))
         self.assertEqual(2, result[0].cyclomatic_complexity)
 
+    def test_hex_number_with_thousands_separator_since_cpp14(self):
+        result = get_cpp_function_list("""int fun(){
+            int a= 0x12ab'34cd; if(b) c; return 0xEF56'7890'1A2B;
+        }""")
+        self.assertEqual(1, len(result))
+        self.assertEqual(2, result[0].cyclomatic_complexity)
+
+    def test_bin_number_with_thousands_separator_since_cpp14(self):
+        result = get_cpp_function_list("""int fun(){
+            int a= 0b0101'1100; if(b) c; return 0b1111'0000'1100'1110;
+        }""")
+        self.assertEqual(1, len(result))
+        self.assertEqual(2, result[0].cyclomatic_complexity)
+
     def test_function_with_no_param_omitted(self):
         result = get_cpp_function_list("int fun(){}")
         self.assertEqual(0, result[0].parameter_count)
diff --git a/test/test_languages/testGo.py b/test/test_languages/testGo.py
index 22fce2a..5a6462d 100644
--- a/test/test_languages/testGo.py
+++ b/test/test_languages/testGo.py
@@ -127,3 +127,28 @@ class Test_parser_for_Go(unittest.TestCase):
                 ''')
         self.assertEqual(0, len(result))
 
+    def test_struct_with_func_followed_by_function_with_receiver(self):
+        result = get_go_function_list('''
+            type Geometry struct {
+                isEqual func(float64, float64) error
+            }
+
+            func (g *Geometry) sayGoodbye() { }
+                ''')
+
+        self.assertEqual(1, len(result))
+        self.assertEqual("sayGoodbye", result[0].name)
+
+    def test_interface_with_func_followed_by_function_with_receiver(self):
+        result = get_go_function_list('''
+            type MyComparator struct{}
+
+            type Comparator interface {
+                Handle(func(int) string)
+            }
+
+            func (m MyComparator) Handle(f func(int) string) {}
+                ''')
+
+        self.assertEqual(1, len(result))
+        self.assertEqual("Handle", result[0].name)