Repository: terryyin/lizard

Issue:
Bug: C++11 ref qualified functions
Lizard misses C++11 ref qualified member functions.
These functions don't appear in the report or the result database.

```cpp
struct A {
  void foo() & {};
  void foo() const & {};
  void foo() && {};
  void foo() const && {};
};

Discussion:
rakhimov: @terryyin This PR is ready to go.

Patch:
diff --git a/lizard_languages/clike.py b/lizard_languages/clike.py
index 1134e96..a17fb03 100644
--- a/lizard_languages/clike.py
+++ b/lizard_languages/clike.py
@@ -235,7 +235,7 @@ class CLikeStates(CodeStateMachine):
         self.context.add_to_long_function_name(token)
 
     def _state_dec_to_imp(self, token):
-        if token == 'const' or token == 'noexcept':
+        if token in ('const', 'noexcept', '&', '&&'):
             self.context.add_to_long_function_name(" " + token)
         elif token == 'throw':
             self._state = self._state_throw


Test patch:
diff --git a/test/testCyclomaticComplexity.py b/test/testCyclomaticComplexity.py
index 346117e..d6efefa 100644
--- a/test/testCyclomaticComplexity.py
+++ b/test/testCyclomaticComplexity.py
@@ -79,3 +79,13 @@ class TestCppCyclomaticComplexity(unittest.TestCase):
         """)
         self.assertEqual(4, result[0].cyclomatic_complexity)
 
+    def test_ref_qualifiers(self):
+        """C++11 rvalue ref qualifiers look like AND operator."""
+        result = get_cpp_function_list(
+                "struct A { void foo() && { return bar() && baz(); } };")
+        self.assertEqual(1, len(result))
+        self.assertEqual(2, result[0].cyclomatic_complexity)
+        result = get_cpp_function_list(
+                "struct A { void foo() const && { return bar() && baz(); } };")
+        self.assertEqual(1, len(result))
+        self.assertEqual(2, result[0].cyclomatic_complexity)
diff --git a/test/test_languages/testCAndCPP.py b/test/test_languages/testCAndCPP.py
index 0928b15..b175fcd 100644
--- a/test/test_languages/testCAndCPP.py
+++ b/test/test_languages/testCAndCPP.py
@@ -423,6 +423,7 @@ class Test_c_cpp_lizard(unittest.TestCase):
         result = get_cpp_function_list('''int fun(struct a){}''')
         self.assertEqual(1, len(result))
 
+
     def test_trailing_return_type(self):
         """C++11 trailing return type for functions."""
         result = get_cpp_function_list("auto foo() -> void {}")
@@ -432,6 +433,21 @@ class Test_c_cpp_lizard(unittest.TestCase):
         self.assertEqual(1, len(result))
         self.assertEqual("foo", result[0].name)
 
+    def test_ref_qualifiers(self):
+        """C++11 ref qualifiers for member functions."""
+        result = get_cpp_function_list("struct A { void foo() & {} };")
+        self.assertEqual(1, len(result))
+        self.assertEqual("A::foo", result[0].name)
+        result = get_cpp_function_list("struct A { void foo() const & {} };")
+        self.assertEqual(1, len(result))
+        self.assertEqual("A::foo", result[0].name)
+        result = get_cpp_function_list("struct A { void foo() && {} };")
+        self.assertEqual(1, len(result))
+        self.assertEqual("A::foo", result[0].name)
+        result = get_cpp_function_list("struct A { void foo() const && {} };")
+        self.assertEqual(1, len(result))
+        self.assertEqual("A::foo", result[0].name)
+
 
 class Test_Preprocessing(unittest.TestCase):