|
3 | 3 |
|
4 | 4 | using namespace BinaryNinja;
|
5 | 5 |
|
| 6 | +namespace { |
| 7 | + |
| 8 | +// Given a selector component such as `initWithPath' and a prefix of `initWith`, returns `path`. |
| 9 | +std::optional<std::string> SelectorComponentWithoutPrefix(std::string_view prefix, std::string_view component) |
| 10 | +{ |
| 11 | + if (component.size() <= prefix.size() || component.rfind(prefix.data(), 0) != 0 |
| 12 | + || !isupper(component[prefix.size()])) |
| 13 | + { |
| 14 | + return std::nullopt; |
| 15 | + } |
| 16 | + |
| 17 | + std::string result(component.substr(prefix.size())); |
| 18 | + |
| 19 | + // Lowercase the first character if the second character is not also uppercase. |
| 20 | + // This ensures we leave initialisms such as `URL` alone. |
| 21 | + if (result.size() > 1 && islower(result[1])) |
| 22 | + result[0] = tolower(result[0]); |
| 23 | + |
| 24 | + return result; |
| 25 | +} |
| 26 | + |
| 27 | +std::string ArgumentNameFromSelectorComponent(std::string component) |
| 28 | +{ |
| 29 | + // TODO: Handle other common patterns such as <do some action>With<arg>: and <do some action>For<arg>: |
| 30 | + for (const auto& prefix : {"initWith", "with", "and", "using", "set", "read", "to", "for"}) |
| 31 | + { |
| 32 | + if (auto argumentName = SelectorComponentWithoutPrefix(prefix, component); argumentName.has_value()) |
| 33 | + return std::move(*argumentName); |
| 34 | + } |
| 35 | + |
| 36 | + return component; |
| 37 | +} |
| 38 | + |
| 39 | +} // namespace |
| 40 | + |
6 | 41 | Ref<Metadata> ObjCProcessor::SerializeMethod(uint64_t loc, const Method& method)
|
7 | 42 | {
|
8 | 43 | std::map<std::string, Ref<Metadata>> methodMeta;
|
@@ -1099,10 +1134,13 @@ bool ObjCProcessor::ApplyMethodType(Class& cls, Method& method, bool isInstanceM
|
1099 | 1134 |
|
1100 | 1135 | for (size_t i = 3; i < typeTokens.size(); i++)
|
1101 | 1136 | {
|
1102 |
| - std::string suffix; |
| 1137 | + std::string name; |
| 1138 | + if (selectorTokens.size() > i - 3) |
| 1139 | + name = ArgumentNameFromSelectorComponent(selectorTokens[i - 3]); |
| 1140 | + else |
| 1141 | + name = "arg"; |
1103 | 1142 |
|
1104 |
| - params.push_back({selectorTokens.size() > i - 3 ? selectorTokens[i - 3] : "arg", |
1105 |
| - typeForQualifiedNameOrType(typeTokens[i]), true, BinaryNinja::Variable()}); |
| 1143 | + params.push_back({std::move(name), typeForQualifiedNameOrType(typeTokens[i]), true, BinaryNinja::Variable()}); |
1106 | 1144 | }
|
1107 | 1145 |
|
1108 | 1146 | auto funcType = BinaryNinja::Type::FunctionType(retType, cc, params);
|
|
0 commit comments