-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Eng/pr getters setters #40842
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
Merged
Merged
Eng/pr getters setters #40842
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
21cc043
fixing setters
ed168d9
adding tests
659d4d5
Removing extras
d57c548
fixing tests
4554ad0
Better naming for properties
51be2d0
Cleanup
fe8d9ed
Add tests
46a690f
Clang format it
f224d80
more refactoring and some more tests
3df96ee
More tests and more fixes
13d528e
Updating tests:
f68274f
Fix the two asserts. Move things around. Remove createImported. Move …
100f8b4
General updates:
1e1bbb0
Fixing Comments left on the PR:
8ac79bf
Fixing tests, and general updates for formatting
6ef20b8
removing extras and passing this on swift.
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
#ifndef SWIFT_CXXMETHODBRIDGING_H | ||
#define SWIFT_CXXMETHODBRIDGING_H | ||
|
||
#include "swift/AST/Decl.h" | ||
#include "clang/AST/DeclCXX.h" | ||
#include "llvm/ADT/StringRef.h" | ||
|
||
#include <string> | ||
namespace swift { | ||
struct CXXMethodBridging { | ||
enum class Kind { unkown, getter, setter, subscript }; | ||
|
||
enum class NameKind { unkown, snake, lower, camel, title }; | ||
|
||
CXXMethodBridging(const clang::CXXMethodDecl *method) : method(method) {} | ||
|
||
Kind classify() { | ||
if (nameIsBlacklist()) | ||
return Kind::unkown; | ||
|
||
// this should be handled as snake case. See: rdar://89453010 | ||
// case. In the future we could | ||
// import these too, though. | ||
auto nameKind = classifyNameKind(); | ||
if (nameKind != NameKind::title && nameKind != NameKind::camel && | ||
nameKind != NameKind::lower) | ||
return Kind::unkown; | ||
|
||
if (getClangName().startswith_insensitive("set")) { | ||
// Setters only have one parameter. | ||
if (method->getNumParams() != 1) | ||
return Kind::unkown; | ||
|
||
// rdar://89453106 (We need to handle imported properties that return a | ||
// reference) | ||
if (method->getParamDecl(0)->getType()->isReferenceType()) | ||
return Kind::unkown; | ||
|
||
return Kind::setter; | ||
} | ||
|
||
// Getters and subscripts cannot return void. | ||
if (method->getReturnType()->isVoidType()) | ||
return Kind::unkown; | ||
|
||
if (getClangName().startswith_insensitive("get")) { | ||
// Getters cannot take arguments. | ||
if (method->getNumParams() != 0) | ||
return Kind::unkown; | ||
|
||
// rdar://89453106 (We need to handle imported properties that return a | ||
// reference) | ||
if (method->getReturnType()->isReferenceType()) | ||
return Kind::unkown; | ||
|
||
return Kind::getter; | ||
} | ||
|
||
// rdar://89453187 (Add subscripts clarification to CXXMethod Bridging to | ||
// clean up importDecl) | ||
return Kind::unkown; | ||
} | ||
|
||
NameKind classifyNameKind() { | ||
bool allLower = llvm::all_of(getClangName(), islower); | ||
|
||
if (getClangName().empty()) | ||
return NameKind::unkown; | ||
|
||
if (getClangName().contains('_')) | ||
return allLower ? NameKind::snake : NameKind::unkown; | ||
|
||
if (allLower) | ||
return NameKind::lower; | ||
|
||
return islower(getClangName().front()) ? NameKind::camel : NameKind::title; | ||
} | ||
|
||
llvm::StringRef getClangName() { | ||
if (!method->getDeclName().isIdentifier()) | ||
return ""; | ||
|
||
return method->getName(); | ||
} | ||
|
||
// this should be handled as snake case. See: rdar://89453010 | ||
std::string importNameAsCamelCaseName() { | ||
std::string output; | ||
auto kind = classify(); | ||
if (kind == Kind::getter || kind == Kind::setter) { | ||
output = getClangName().drop_front(3).str(); | ||
} else { | ||
output = getClangName().str(); | ||
} | ||
|
||
if (output.empty()) | ||
return output; | ||
|
||
// No work to do. | ||
if (classifyNameKind() == NameKind::lower) | ||
return output; | ||
|
||
// The first character is always lowercase. | ||
output.front() = std::tolower(output.front()); | ||
|
||
// We already lowercased the first element, so start at one. Look at the | ||
// current element and the next one. To handle cases like UTF8String, start | ||
// making all the uppercase characters lower, until we see an upper case | ||
// character followed by a lower case character (i.e., "St"). | ||
for (size_t i = 1; i < output.size(); i++) { | ||
size_t next = i + 1; | ||
|
||
// If we see two upper case characters (or an upper case character and a | ||
// number) make the current character lower case. | ||
if (std::isupper(output[i]) && | ||
(std::isupper(output[next]) || std::isdigit(output[next]))) { | ||
output[i] = std::tolower(output[i]); | ||
// If we found an upper case character followed by a lower case | ||
// character, we went far enough. We're done. | ||
} else if (std::isupper(output[i]) && std::islower(output[next])) { | ||
break; | ||
// If we got to the end of the string, we're done. | ||
} else if (std::isupper(output[i]) && next + 1 > output.size()) { | ||
output[i] = std::tolower(output[i]); | ||
break; | ||
} | ||
} | ||
|
||
return output; | ||
} | ||
|
||
std::string importNameAsTitleCaseName() { | ||
auto output = importNameAsCamelCaseName(); | ||
output.front() = std::toupper(output.front()); | ||
return output; | ||
} | ||
|
||
private: | ||
const clang::CXXMethodDecl *method = nullptr; | ||
|
||
bool nameIsBlacklist() { | ||
auto loweredName = getClangName().lower(); | ||
// Names that start with "get" or "set" but aren't getters or setters. | ||
return loweredName == "getter" || loweredName == "setter" || | ||
loweredName == "get" || loweredName == "set"; | ||
} | ||
}; | ||
} // namespace swift | ||
#endif // SWIFT_CXXMETHODBRIDGING_H |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.