Repository: opencv/opencv
File: modules/js/generator/embindgen.py (Python)

Code before:

        binding_text = None
        binding_text_list = []

        for index, variant in enumerate(func.variants):
            factory = False
            #TODO if variant.is_class_method and variant.rettype == ('Ptr<' + class_info.name + '>'):
            if (not class_info == None) and variant.rettype == ('Ptr<' + class_info.name + '>') or (func.name.startswith("create") and variant.rettype):
                factory = True
                base_class_name = variant.rettype
                base_class_name = base_class_name.replace("Ptr<","").replace(">","").strip()
                if base_class_name in self.classes:
                    self.classes[base_class_name].has_smart_ptr = True
                else:
                    print(base_class_name, ' not found in classes for registering smart pointer using ', class_info.name, 'instead')
                    self.classes[class_info.name].has_smart_ptr = True


            # Return type
            ret_type = 'void' if variant.rettype.strip() == '' else variant.rettype

            ret_type = ret_type.strip()
            # Same namespace fix for factory methods: Ptr<EdgeDrawing> -> Ptr<cv::ximgproc::EdgeDrawing>
            if factory and class_info is not None and ret_type.startswith('Ptr<'):
                inner = ret_type[len('Ptr<'):-1].strip()
                if '::' not in inner:
                    ret_type = 'Ptr<%s>' % class_info.cname

            if ret_type.startswith('Ptr'): #smart pointer
                ptr_type = ret_type.replace('Ptr<', '').replace('>', '')
                if ptr_type in type_dict:
                    ret_type = type_dict[ptr_type]
            for key in type_dict:
                if key in ret_type:
                    # Replace types. Instead of ret_type.replace we use regular
                    # expression to exclude false matches.
                    # See https://github.com/opencv/opencv/issues/15514
                    ret_type = re.sub(r"\b" + key + r"\b", type_dict[key], ret_type)
            if variant.constret and ret_type.startswith('const') == False:
                ret_type = 'const ' + ret_type
            if variant.refret and ret_type.endswith('&') == False:
                ret_type += '&'

            arg_types = []
            orig_arg_types = []
            def_args = []
            for arg in variant.args:
                if arg.tp in type_dict:
                    arg_type = type_dict[arg.tp]
                else:
                    arg_type = arg.tp

Review comment (suggestion):
The fix assumes that the unqualified type inside `Ptr<...>` always refers to the class represented by `class_info`. However, this may not be correct if a method returns a pointer to a different class. Consider checking if `inner` matches `class_info.name` before replacing it with `class_info.cname`. For example:

```python
if factory and class_info is not None and ret_type.startswith('Ptr<'):
    inner = ret_type[len('Ptr<'):-1].strip()
    if '::' not in inner and inner == class_info.name:
        ret_type = 'Ptr<%s>' % class_info.cname
```

This ensures we only qualify the type when it actually refers to the current class.
```suggestion
                if '::' not in inner and inner == class_info.name:
```

Code after:

        binding_text = None
        binding_text_list = []

        for index, variant in enumerate(func.variants):
            factory = False
            #TODO if variant.is_class_method and variant.rettype == ('Ptr<' + class_info.name + '>'):
            if (not class_info == None) and variant.rettype == ('Ptr<' + class_info.name + '>') or (func.name.startswith("create") and variant.rettype):
                factory = True
                base_class_name = variant.rettype
                base_class_name = base_class_name.replace("Ptr<","").replace(">","").strip()
                if base_class_name in self.classes:
                    self.classes[base_class_name].has_smart_ptr = True
                else:
                    print(base_class_name, ' not found in classes for registering smart pointer using ', class_info.name, 'instead')
                    self.classes[class_info.name].has_smart_ptr = True


            # Return type
            ret_type = 'void' if variant.rettype.strip() == '' else variant.rettype

            ret_type = ret_type.strip()
            # Same namespace fix for factory methods: Ptr<EdgeDrawing> -> Ptr<cv::ximgproc::EdgeDrawing>
            if factory and class_info is not None and ret_type.startswith('Ptr<'):
                inner = ret_type[len('Ptr<'):-1].strip()
                if '::' not in inner and inner == class_info.name:
                    ret_type = 'Ptr<%s>' % class_info.cname

            if ret_type.startswith('Ptr'): #smart pointer
                ptr_type = ret_type.replace('Ptr<', '').replace('>', '')
                if ptr_type in type_dict:
                    ret_type = type_dict[ptr_type]
            for key in type_dict:
                if key in ret_type:
                    # Replace types. Instead of ret_type.replace we use regular
                    # expression to exclude false matches.
                    # See https://github.com/opencv/opencv/issues/15514
                    ret_type = re.sub(r"\b" + key + r"\b", type_dict[key], ret_type)
            if variant.constret and ret_type.startswith('const') == False:
                ret_type = 'const ' + ret_type
            if variant.refret and ret_type.endswith('&') == False:
                ret_type += '&'

            arg_types = []
            orig_arg_types = []
            def_args = []
            for arg in variant.args:
                if arg.tp in type_dict:
                    arg_type = type_dict[arg.tp]
                else:
                    arg_type = arg.tp