From a2e637f4e1d6a14a67f96c151c1ae61c5dc40bf6 Mon Sep 17 00:00:00 2001 From: Arsam Date: Sat, 4 May 2024 16:05:35 +0200 Subject: [PATCH 1/3] fixed a bug where results in stubs would not be named --- .../api_analyzer/_ast_visitor.py | 105 ++++++++++-------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/src/safeds_stubgen/api_analyzer/_ast_visitor.py b/src/safeds_stubgen/api_analyzer/_ast_visitor.py index 17492c30..296a123d 100644 --- a/src/safeds_stubgen/api_analyzer/_ast_visitor.py +++ b/src/safeds_stubgen/api_analyzer/_ast_visitor.py @@ -466,22 +466,29 @@ def _parse_results( # Create Result objects and try to find a matching docstring name all_results = [] name_generator = result_name_generator() - for type_ in return_results: - result_docstring = ResultDocstring() - for docstring in result_docstrings: - if hash(docstring.type) == hash(type_): - result_docstring = docstring - break - result_name = result_docstring.name if result_docstring.name else next(name_generator) - - result = Result( + if len(return_results) == 1 == len(result_docstrings): + result_name = result_docstrings[0].name or next(name_generator) + all_results = [Result( id=f"{function_id}/{result_name}", - type=type_, + type=return_results[0], name=f"{result_name}", - ) + )] + else: + for type_ in return_results: + result_docstring = ResultDocstring() + for docstring in result_docstrings: + if hash(docstring.type) == hash(type_): + result_docstring = docstring + break - all_results.append(result) + result_name = result_docstring.name or next(name_generator) + + all_results.append(Result( + id=f"{function_id}/{result_name}", + type=type_, + name=f"{result_name}", + )) return all_results @@ -582,39 +589,47 @@ def _create_inferred_results( # Create Result objects name_generator = result_name_generator() inferred_results = [] - for result_list in result_array: - result_count = len(result_list) - if result_count == 1: - result_type = result_list[0] - else: - result_type = sds_types.UnionType(result_list) - - # Search for matching docstrings for each result for the name - result_docstring = ResultDocstring() - if docstrings: - if isinstance(result_type, sds_types.UnionType): - possible_type: sds_types.AbstractType | None - if len(docstrings) > 1: - docstring_types = [docstring.type for docstring in docstrings if docstring.type is not None] - possible_type = sds_types.UnionType(types=docstring_types) - else: - possible_type = docstrings[0].type - if possible_type == result_type: - result_docstring = docstrings[0] + if 1 == len(result_array) == len(result_array[0]) == len(docstrings): + result_name = docstrings[0].name or next(name_generator) + inferred_results = [Result( + id=f"{function_id}/{result_name}", + type=result_array[0][0], + name=result_name, + )] + else: + for result_list in result_array: + result_count = len(result_list) + if result_count == 1: + result_type = result_list[0] else: - for docstring in docstrings: - if hash(docstring.type) == hash(result_type): - result_docstring = docstring - break - - result_name = result_docstring.name or next(name_generator) - inferred_results.append( - Result( - id=f"{function_id}/{result_name}", - type=result_type, - name=result_name, - ), - ) + result_type = sds_types.UnionType(result_list) + + # Search for matching docstrings for each result for the name + result_docstring = ResultDocstring() + if docstrings: + if isinstance(result_type, sds_types.UnionType): + possible_type: sds_types.AbstractType | None + if len(docstrings) > 1: + docstring_types = [docstring.type for docstring in docstrings if docstring.type is not None] + possible_type = sds_types.UnionType(types=docstring_types) + else: + possible_type = docstrings[0].type + if possible_type == result_type: + result_docstring = docstrings[0] + else: + for docstring in docstrings: + if hash(docstring.type) == hash(result_type): + result_docstring = docstring + break + + result_name = result_docstring.name or next(name_generator) + inferred_results.append( + Result( + id=f"{function_id}/{result_name}", + type=result_type, + name=result_name, + ), + ) return inferred_results @@ -859,7 +874,7 @@ def _get_reexported_by(self, qname: str) -> list[Module]: for mod in self.api.reexport_map[reexport_name_forward]: reexported_by.add(mod) - reexport_name_backward = ".".join(path[-i - 1 :]) + reexport_name_backward = ".".join(path[-i - 1:]) if reexport_name_backward in self.api.reexport_map: for mod in self.api.reexport_map[reexport_name_backward]: reexported_by.add(mod) From eca6166bb76d19c8494e900332fbd5f21d2eabf7 Mon Sep 17 00:00:00 2001 From: Arsam Date: Sat, 4 May 2024 16:18:44 +0200 Subject: [PATCH 2/3] added tests --- .../data/docstring_parser_package/numpydoc.py | 24 +++++++++++++++++++ ...string_creation[numpydoc-NUMPYDOC].sdsstub | 18 ++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/tests/data/docstring_parser_package/numpydoc.py b/tests/data/docstring_parser_package/numpydoc.py index d8f64f02..bcf08cd9 100644 --- a/tests/data/docstring_parser_package/numpydoc.py +++ b/tests/data/docstring_parser_package/numpydoc.py @@ -524,3 +524,27 @@ def numpy_sequence_types(a: SequenceTypeVar[list]) -> SequenceTypeVar2[int]: this will be the return value """ pass + + +def numpy_named_result_without_type() -> str: + """ + numpy_named_result_without_type + + Returns + ------- + named_result : + this will be the return value + """ + return "result" + + +def numpy_named_result_without_type_inferred(): + """ + numpy_named_result_without_type_inferred + + Returns + ------- + named_result : + this will be the return value + """ + return "result" diff --git a/tests/safeds_stubgen/stubs_generator/__snapshots__/test_generate_stubs/test_stub_docstring_creation[numpydoc-NUMPYDOC].sdsstub b/tests/safeds_stubgen/stubs_generator/__snapshots__/test_generate_stubs/test_stub_docstring_creation[numpydoc-NUMPYDOC].sdsstub index 22189578..7e7400aa 100644 --- a/tests/safeds_stubgen/stubs_generator/__snapshots__/test_generate_stubs/test_stub_docstring_creation[numpydoc-NUMPYDOC].sdsstub +++ b/tests/safeds_stubgen/stubs_generator/__snapshots__/test_generate_stubs/test_stub_docstring_creation[numpydoc-NUMPYDOC].sdsstub @@ -175,6 +175,24 @@ fun numpySequenceTypes( a: SequenceTypeVar> ) -> namedResult: SequenceTypeVar2 +/** + * numpy_named_result_without_type + * + * @result namedResult this will be the return value + */ +@Pure +@PythonName("numpy_named_result_without_type") +fun numpyNamedResultWithoutType() -> namedResult: String + +/** + * numpy_named_result_without_type_inferred + * + * @result namedResult this will be the return value + */ +@Pure +@PythonName("numpy_named_result_without_type_inferred") +fun numpyNamedResultWithoutTypeInferred() -> namedResult: String + /** * ClassWithDocumentation. Code:: * From ac1b487972b26cc3cd147ff90f6510a80961bf92 Mon Sep 17 00:00:00 2001 From: megalinter-bot <129584137+megalinter-bot@users.noreply.github.com> Date: Sat, 4 May 2024 14:20:27 +0000 Subject: [PATCH 3/3] style: apply automated linter fixes --- .../api_analyzer/_ast_visitor.py | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/safeds_stubgen/api_analyzer/_ast_visitor.py b/src/safeds_stubgen/api_analyzer/_ast_visitor.py index 296a123d..ead8f44a 100644 --- a/src/safeds_stubgen/api_analyzer/_ast_visitor.py +++ b/src/safeds_stubgen/api_analyzer/_ast_visitor.py @@ -469,11 +469,13 @@ def _parse_results( if len(return_results) == 1 == len(result_docstrings): result_name = result_docstrings[0].name or next(name_generator) - all_results = [Result( - id=f"{function_id}/{result_name}", - type=return_results[0], - name=f"{result_name}", - )] + all_results = [ + Result( + id=f"{function_id}/{result_name}", + type=return_results[0], + name=f"{result_name}", + ), + ] else: for type_ in return_results: result_docstring = ResultDocstring() @@ -484,11 +486,13 @@ def _parse_results( result_name = result_docstring.name or next(name_generator) - all_results.append(Result( - id=f"{function_id}/{result_name}", - type=type_, - name=f"{result_name}", - )) + all_results.append( + Result( + id=f"{function_id}/{result_name}", + type=type_, + name=f"{result_name}", + ), + ) return all_results @@ -591,11 +595,13 @@ def _create_inferred_results( inferred_results = [] if 1 == len(result_array) == len(result_array[0]) == len(docstrings): result_name = docstrings[0].name or next(name_generator) - inferred_results = [Result( - id=f"{function_id}/{result_name}", - type=result_array[0][0], - name=result_name, - )] + inferred_results = [ + Result( + id=f"{function_id}/{result_name}", + type=result_array[0][0], + name=result_name, + ), + ] else: for result_list in result_array: result_count = len(result_list) @@ -874,7 +880,7 @@ def _get_reexported_by(self, qname: str) -> list[Module]: for mod in self.api.reexport_map[reexport_name_forward]: reexported_by.add(mod) - reexport_name_backward = ".".join(path[-i - 1:]) + reexport_name_backward = ".".join(path[-i - 1 :]) if reexport_name_backward in self.api.reexport_map: for mod in self.api.reexport_map[reexport_name_backward]: reexported_by.add(mod)