-
Notifications
You must be signed in to change notification settings - Fork 3.2k
[bct] Checker refactoring + new overload checker #37284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c6fce15
aa43872
11d8e8e
0dffaa1
170ed4e
b315249
dfa5d28
22b813b
726a7c4
a51a162
9a090fc
2ab4ae9
ed2fd95
03fcf35
592762d
01f8ca7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| #!/usr/bin/env python | ||
|
|
||
| # -------------------------------------------------------------------------------------------- | ||
| # Copyright (c) Microsoft Corporation. All rights reserved. | ||
| # Licensed under the MIT License. See License.txt in the project root for license information. | ||
| # -------------------------------------------------------------------------------------------- | ||
| import sys | ||
| import os | ||
| sys.path.append(os.path.abspath("../../scripts/breaking_changes_checker")) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this needed?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wasnt able to reference the _models from here for some reason :/ I'll look back into why this was necessary in the future (tracking issue: #37914) |
||
| from _models import CheckerType | ||
| import jsondiff | ||
|
|
||
| def parse_overload_signature(method_name, overload) -> str: | ||
| parsed_overload_signature = f"def {method_name}(" + ", ".join([f"{name}: {data['type']}" for name, data in overload["parameters"].items()]) + ")" | ||
| if overload["return_type"] is not None: | ||
| parsed_overload_signature += f" -> {overload['return_type']}" | ||
| return parsed_overload_signature | ||
|
|
||
| class AddedMethodOverloadChecker: | ||
| node_type = CheckerType.FUNCTION_OR_METHOD | ||
| name = "AddedMethodOverload" | ||
| is_breaking = False | ||
| message = { | ||
| "default": "Method `{}.{}` has a new overload `{}`", | ||
| } | ||
|
|
||
| def run_check(self, diff, stable_nodes, current_nodes, **kwargs): | ||
| module_name = kwargs.get("module_name") | ||
| class_name = kwargs.get("class_name") | ||
| changes_list = [] | ||
| for method_name, method_components in diff.items(): | ||
| # We aren't checking for deleted methods in this checker | ||
| if isinstance(method_name, jsondiff.Symbol): | ||
| continue | ||
| for overload in method_components.get("overloads", []): | ||
| if isinstance(overload, jsondiff.Symbol): | ||
| if overload.label == "insert": | ||
| for _, added_overload in method_components["overloads"][overload]: | ||
| parsed_overload_signature = parse_overload_signature(method_name, added_overload) | ||
| changes_list.append((self.message["default"], self.name, module_name, class_name, method_name, parsed_overload_signature)) | ||
| elif isinstance(overload, int): | ||
| current_node_overload = current_nodes[module_name]["class_nodes"][class_name]["methods"][method_name]["overloads"][overload] | ||
| parsed_overload_signature = f"def {method_name}(" + ", ".join([f"{name}: {data['type']}" for name, data in current_node_overload["parameters"].items()]) + ")" | ||
| if current_node_overload["return_type"] is not None: | ||
| parsed_overload_signature += f" -> {current_node_overload['return_type']}" | ||
| changes_list.append((self.message["default"], self.name, module_name, class_name, method_name, parsed_overload_signature)) | ||
| else: | ||
| # this case is for when the overload is not a symbol and simply shows as a new overload in the diff | ||
| parsed_overload_signature = parse_overload_signature(method_name, overload) | ||
| changes_list.append((self.message["default"], self.name, module_name, class_name, method_name, parsed_overload_signature)) | ||
| return changes_list | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| #!/usr/bin/env python | ||
|
|
||
| # -------------------------------------------------------------------------------------------- | ||
| # Copyright (c) Microsoft Corporation. All rights reserved. | ||
| # Licensed under the MIT License. See License.txt in the project root for license information. | ||
| # -------------------------------------------------------------------------------------------- | ||
| import sys | ||
| import os | ||
| sys.path.append(os.path.abspath("../../scripts/breaking_changes_checker")) | ||
| from _models import CheckerType | ||
| import jsondiff | ||
|
|
||
| class RemovedMethodOverloadChecker: | ||
| node_type = CheckerType.FUNCTION_OR_METHOD | ||
| name = "RemovedMethodOverload" | ||
| is_breaking = True | ||
| message = { | ||
| "default": "`{}.{}` had an overload `{}` removed", | ||
| "all": "`{}.{}` had all overloads removed" | ||
| } | ||
|
|
||
| def run_check(self, diff, stable_nodes, current_nodes, **kwargs): | ||
| module_name = kwargs.get("module_name") | ||
| class_name = kwargs.get("class_name") | ||
| bc_list = [] | ||
| # This is a new module, so we won't check for removed overloads | ||
| if module_name not in stable_nodes: | ||
| return bc_list | ||
| if class_name not in stable_nodes[module_name]["class_nodes"]: | ||
| # This is a new class, so we don't need to check for removed overloads | ||
| return bc_list | ||
| for method_name, method_components in diff.items(): | ||
| # We aren't checking for deleted methods in this checker | ||
| if isinstance(method_name, jsondiff.Symbol): | ||
| continue | ||
| # Check if all of the overloads were deleted for an existing stable method | ||
| if len(method_components.get("overloads", [])) == 0: | ||
| if method_name in stable_nodes[module_name]["class_nodes"][class_name]["methods"] and \ | ||
| "overloads" in stable_nodes[module_name]["class_nodes"][class_name]["methods"][method_name]: | ||
| if len(stable_nodes[module_name]["class_nodes"][class_name]["methods"][method_name]["overloads"]) > 0: | ||
| bc_list.append((self.message["all"], self.name, module_name, class_name, method_name)) | ||
| continue | ||
| # Check for specific overloads that were deleted | ||
| for overload in method_components.get("overloads", []): | ||
| if isinstance(overload, jsondiff.Symbol): | ||
| if overload.label == "delete": | ||
| for deleted_overload in method_components["overloads"][overload]: | ||
| stable_node_overloads = stable_nodes[module_name]["class_nodes"][class_name]["methods"][method_name]["overloads"][deleted_overload] | ||
| parsed_overload_signature = f"def {method_name}(" + ", ".join([f"{name}: {data['type']}" for name, data in stable_node_overloads["parameters"].items()]) + ")" | ||
| if stable_node_overloads["return_type"] is not None: | ||
| parsed_overload_signature += f" -> {stable_node_overloads['return_type']}" | ||
| bc_list.append((self.message["default"], self.name, module_name, class_name, method_name, parsed_overload_signature)) | ||
| return bc_list |
Uh oh!
There was an error while loading. Please reload this page.