diff --git a/CppHeaderParser/CppHeaderParser.py b/CppHeaderParser/CppHeaderParser.py
index f142278..3beb3d0 100644
--- a/CppHeaderParser/CppHeaderParser.py
+++ b/CppHeaderParser/CppHeaderParser.py
@@ -936,7 +936,17 @@ def _params_helper1(self, stack):
             elif a.startswith("__attribute__((__const__))"):
                 stack = stack[6:]
 
-        stack = stack[stack.index("(") + 1 :]
+        last_paren_index = len(stack) - stack[-1::-1].index(")") - 1
+        open_paren_count = 1
+        method_paren_start_idx = last_paren_index-1
+        while open_paren_count > 0:
+            if stack[method_paren_start_idx] == ")":
+                open_paren_count+=1
+            elif stack[method_paren_start_idx] == "(":
+                open_paren_count-=1
+            method_paren_start_idx -= 1
+
+        stack = stack[method_paren_start_idx + 2 :]
         if not stack:
             return []
         if (
@@ -998,33 +1008,6 @@ def __init__(self, nameStack, curClass, methinfo, curTemplate, doxygen, location
         if doxygen:
             self["doxygen"] = doxygen
 
-        # Remove leading keywords
-        for i, word in enumerate(nameStack):
-            if word not in Resolver.C_KEYWORDS:
-                nameStack = nameStack[i:]
-                break
-
-        if "operator" in nameStack:
-            rtnType = " ".join(nameStack[: nameStack.index("operator")])
-            self["name"] = "".join(
-                nameStack[nameStack.index("operator") : nameStack.index("(")]
-            )
-        else:
-            rtnType = " ".join(nameStack[: nameStack.index("(") - 1])
-            self["name"] = " ".join(
-                nameStack[nameStack.index("(") - 1 : nameStack.index("(")]
-            )
-
-        if len(rtnType) == 0 or self["name"] == curClass:
-            rtnType = "void"
-
-        self["rtnType"] = (
-            rtnType.replace(" :: ", "::")
-            .replace(" < ", "<")
-            .replace(" > ", "> ")
-            .replace(">>", "> >")
-            .replace(" ,", ",")
-        )
 
         # deal with "noexcept" specifier/operator
         self["noexcept"] = None
@@ -1064,6 +1047,8 @@ def __init__(self, nameStack, curClass, methinfo, curTemplate, doxygen, location
                     break
 
         self.update(methinfo)
+        if len(self["rtnType"]) == 0 or self["name"] == curClass:
+             self["rtnType"] = "void"
         set_location_info(self, location)
 
         paramsStack = self._params_helper1(nameStack)
@@ -1304,6 +1289,7 @@ def __init__(self, nameStack, doxygen, location, **kwargs):
     def _filter_name(self, name):
         name = name.replace(" :", ":").replace(": ", ":")
         name = name.replace(" < ", "<")
+        name = name.replace(" ( ", "(").replace(" ) ", ")")
         name = name.replace(" > ", "> ").replace(">>", "> >")
         name = name.replace(") >", ")>")
         name = name.replace(" {", "{").replace(" }", "}")
@@ -2168,7 +2154,7 @@ def finalize(self):
     }
 
     def parse_method_type(self, stack):
-        trace_print("meth type info", stack)
+        debug_print("meth type info %s", stack)
         info = {
             "debug": " ".join(stack)
             .replace(" :: ", "::")
@@ -2183,13 +2169,57 @@ def parse_method_type(self, stack):
 
         info.update(self._method_type_defaults)
 
-        header = stack[: stack.index("(")]
+        last_paren_index = len(stack) - stack[-1::-1].index(")") - 1
+        open_paren_count = 1
+        method_paren_start_idx = last_paren_index-1
+        while open_paren_count > 0:
+            if stack[method_paren_start_idx] == ")":
+                open_paren_count+=1
+            elif stack[method_paren_start_idx] == "(":
+                open_paren_count-=1
+            method_paren_start_idx -= 1
+
+        header = stack[: method_paren_start_idx+1]
         header = " ".join(header)
+        # Replace fields that would mess up our re-split below
         header = header.replace(" :: ", "::")
         header = header.replace(" < ", "<")
         header = header.replace(" > ", "> ")
+        header = header.replace("> >", ">>")
         header = header.replace("default ", "default")
         header = header.strip()
+        # Remove leading keywords, splitting on spaces to avoid removing keywords embedded in other words
+        
+        # Re-split to find method declarations like A::B::meth() that were formed by joining separate tokens
+        header = header.split()
+        name = header.pop()
+        for word in Resolver.C_KEYWORDS.union(set(ignoreSymbols)):
+            if word in header:
+                info[word] = True
+                header.remove(word)
+        header = " ".join(header)
+        # Now replace fields for aesthetics
+        header = header.replace(" (", "(")
+        header = header.replace("( ", "(")
+        header = header.replace(" )", ")")
+        header = header.replace(") ", ")")
+        header = header.replace(" ,", ",")
+        if "operator" in stack:
+            info["rtnType"] = " ".join(stack[: stack.index("operator")])
+            op = "".join(
+                stack[stack.index("operator")+1 : method_paren_start_idx+1]
+            )
+            if not op:
+                if " ".join(["operator", "(", ")", "("]) in " ".join(stack):
+                    op = "()"
+                else:
+                    debug_print("Error parsing operator")
+                    return None
+            name = "operator"+op
+            info["operator"] = op
+        else:
+            info["rtnType"] = header
+        info["returns"] = info["rtnType"]
 
         if stack[-1] == "{":
             info["defined"] = True
@@ -2210,32 +2240,9 @@ def parse_method_type(self, stack):
             elif stack[-2] == "delete":
                 info["deleted"] = True
 
-        r = header.split()
-        name = None
-        if "operator" in stack:  # rare case op overload defined outside of class
-            op = stack[stack.index("operator") + 1 : stack.index("(")]
-            op = "".join(op)
-            if not op:
-                if " ".join(["operator", "(", ")", "("]) in " ".join(stack):
-                    op = "()"
-                else:
-                    trace_print("Error parsing operator")
-                    return None
-
-            info["operator"] = op
-            name = "operator" + op
-            a = stack[: stack.index("operator")]
-
-        elif r:
-            name = r[-1]
-            a = r[:-1]  # strip name
 
-        if name is None:
-            return None
         # if name.startswith('~'): name = name[1:]
 
-        while a and a[0] == "}":  # strip - can have multiple } }
-            a = a[1:]
 
         if "::" in name:
             # klass,name = name.split('::')    # methods can be defined outside of class
@@ -2254,7 +2261,7 @@ def parse_method_type(self, stack):
                 info["defined"] = True
                 info["default"] = True
             name = name[1:]
-        elif not a or (name == self.curClass and len(self.curClass)):
+        elif (name == self.curClass and len(self.curClass)):
             info["constructor"] = True
             if "default;" in stack:
                 info["defined"] = True
@@ -2262,27 +2269,6 @@ def parse_method_type(self, stack):
 
         info["name"] = name
 
-        for tag in self.C_KEYWORDS:
-            if tag in a:
-                info[tag] = True
-                a.remove(tag)  # inplace
-        if "template" in a:
-            a.remove("template")
-            b = " ".join(a)
-            if ">" in b:
-                info["template"] = b[: b.index(">") + 1]
-                info["returns"] = b[
-                    b.index(">") + 1 :
-                ]  # find return type, could be incorrect... TODO
-                if "<typename" in info["template"].split():
-                    typname = info["template"].split()[-1]
-                    typname = typname[:-1]  # strip '>'
-                    if typname not in self._template_typenames:
-                        self._template_typenames.append(typname)
-            else:
-                info["returns"] = " ".join(a)
-        else:
-            info["returns"] = " ".join(a)
         info["returns"] = info["returns"].replace(" <", "<").strip()
 
         ## be careful with templates, do not count pointers inside template
diff --git a/test/test_CppHeaderParser.py b/test/test_CppHeaderParser.py
index c454a32..cfc35c7 100644
--- a/test/test_CppHeaderParser.py
+++ b/test/test_CppHeaderParser.py
@@ -1535,7 +1535,7 @@ def test_name_0(self):
     def test_type_0(self):
         self.assertEqual(
             self.cppHeader.classes["DriverFuncs"]["properties"]["public"][0]["type"],
-            "void * ( * ) ( )",
+            "void *(* )()",
         )
 
     def test_function_pointer_field_0(self):
@@ -1555,7 +1555,7 @@ def test_name_1(self):
     def test_type_1(self):
         self.assertEqual(
             self.cppHeader.classes["DriverFuncs"]["properties"]["public"][1]["type"],
-            "void ( * ) ( void * buf, int buflen )",
+            "void(* )(void * buf, int buflen )",
         )
 
     def test_function_pointer_field_1(self):
@@ -1631,7 +1631,7 @@ def setUp(self):
     def test_rtn_type(self):
         self.assertEqual(
             self.cppHeader.classes["AlmondClass"]["methods"]["public"][0]["rtnType"],
-            "std::map<unsigned, std::pair<unsigned, SnailTemplateClass<SnailNamespace::SnailClass> > >",
+            "std::map<unsigned, std::pair<unsigned, SnailTemplateClass<SnailNamespace::SnailClass>>>",
         )
 
     def test_param_1_name(self):
@@ -2538,7 +2538,7 @@ def test_set_callback(self):
         )
         self.assertEqual(
             self.cppHeader.functions[8]["parameters"][1]["type"],
-            "long ( * ) ( struct test_st *, int, const char *, int long, long, long )",
+            "long(* )(struct test_st *, int, const char *, int long, long, long )",
         )
 
 
@@ -2851,8 +2851,8 @@ def test_using(self):
                     "desc": None,
                     "name": "",
                     "namespace": "std::",
-                    "raw_type": "std::function<void ( )>",
-                    "type": "function<void ( )>",
+                    "raw_type": "std::function<void()>",
+                    "type": "function<void()>",
                     "typealias": "VoidFunction",
                     "using_type": "typealias",
                 }
@@ -2909,11 +2909,11 @@ def test_fn(self):
                     "raw_type": "std::string",
                 },
                 {
-                    "type": "function<void ( )>",
+                    "type": "function<void()>",
                     "name": "fn",
                     "desc": None,
                     "namespace": "std::",
-                    "raw_type": "std::function<void ( )>",
+                    "raw_type": "std::function<void()>",
                 },
                 {
                     "type": "thing",
@@ -2946,11 +2946,11 @@ def test_class(self):
                     "raw_type": "std::string",
                 },
                 {
-                    "type": "function<int ( )>",
+                    "type": "function<int()>",
                     "name": "fn",
                     "desc": None,
                     "namespace": "std::",
-                    "raw_type": "std::function<int ( )>",
+                    "raw_type": "std::function<int()>",
                 },
                 {
                     "type": "thing",
@@ -4063,5 +4063,73 @@ def test_fn(self):
         self.assertEqual(c.typedefs["mmmmp"], "typedef int ( * ) ( int , int )")
 
 
+class DecltypeMethodReturnClass_meth1(unittest.TestCase):
+    def setUp(self):
+        self.cppHeader = CppHeaderParser.CppHeader(
+            """
+#include <vector>
+#include <string>
+using namespace std;
+
+class DecltypeMethodReturnClass
+{
+public:
+	const int returnInt();
+
+    decltype(returnInt()) meth1(decltype(returnInt()) arg1);
+
+    const std::optional<decltype(returnInt())> meth2(const decltype(returnInt()) v1);
+
+    template<typename T>
+    decltype(T::Q) meth3(int v1);
+
+}; 
+""",
+            "string",
+        )
+
+    def test_name(self):
+        self.assertEqual(
+            self.cppHeader.classes["DecltypeMethodReturnClass"]["methods"]["public"][1]["name"],
+            "meth1",
+        )
+        self.assertEqual(
+            self.cppHeader.classes["DecltypeMethodReturnClass"]["methods"]["public"][2]["name"],
+            "meth2",
+        )
+        self.assertEqual(
+            self.cppHeader.classes["DecltypeMethodReturnClass"]["methods"]["public"][3]["name"],
+            "meth3",
+        )
+
+    def test_rtntype(self):
+        self.assertEqual(
+            self.cppHeader.classes["DecltypeMethodReturnClass"]["methods"]["public"][1]["rtnType"],
+            "decltype(returnInt())",
+        )
+        self.assertEqual(
+            self.cppHeader.classes["DecltypeMethodReturnClass"]["methods"]["public"][2]["rtnType"],
+            "const std::optional<decltype(returnInt())>",
+        )
+        self.assertEqual(
+            self.cppHeader.classes["DecltypeMethodReturnClass"]["methods"]["public"][3]["rtnType"],
+            "decltype(T::Q)",
+        )
+
+    def test_parameters(self):
+        self.assertEqual(
+            self.cppHeader.classes["DecltypeMethodReturnClass"]["methods"]["public"][1]["parameters"][0]['type'],
+            "decltype(returnInt() )",
+        )
+        self.assertEqual(
+            self.cppHeader.classes["DecltypeMethodReturnClass"]["methods"]["public"][2]["parameters"][0]['type'],
+            "const decltype(returnInt() )",
+        )
+        self.assertEqual(
+            self.cppHeader.classes["DecltypeMethodReturnClass"]["methods"]["public"][3]["parameters"][0]['type'],
+            "int",
+        )
+
+
 if __name__ == "__main__":
     unittest.main()