This is an archive of the discontinued LLVM Phabricator instance.

add prefix with '_' support for property name. Corresponding apple dev doc: https://developer.apple.com/library/content/qa/qa1908/_index.html
ClosedPublic

Authored by Wizard on Jan 23 2018, 9:56 PM.

Event Timeline

Wizard created this revision.Jan 23 2018, 9:56 PM
benhamilton added inline comments.Jan 24 2018, 9:31 AM
clang-tidy/objc/PropertyDeclarationCheck.cpp
62–83

Instead of bool isCategory, how about an enum NamingStyle:

enum NamingStyle {
  StandardProperty = 1,
  CategoryProperty = 2,
}
119

I think this is an off-by-one error, right? Change:

i < PropertyName.size() - 1

to

i < PropertyName.size()
120–122

Do we really want a leading _ to count? I think this might need to be a regular expression instead, something like:

^[a-zA-Z][a-zA-Z0-9]+_[a-zA-Z0-9][a-zA-Z0-9_]*$
137

I don't understand what this is doing. Why are we replacing things in a regex?

I don't think this is very maintainable. Can you rewrite it for legibility, please?

158

Is a class extension treated as a category? If so, we probably need to treat it specially.

e.g.:

Foo.h:

@interface Foo
@end

Foo.m:

@interface Foo ()
@property (nonatomic, readonly) int foo_bar;
@end

should not be allowed.

Can you handle this and add tests, please?

Wizard added inline comments.Jan 24 2018, 11:16 AM
clang-tidy/objc/PropertyDeclarationCheck.cpp
119

I was thinking of not letting go anything that ends with "_" otherwise I have to do more sanity check later.

120–122

Yes it is better to use a regex instead. I would use ^[a-z]+_[a-zA-Z0-9][a-zA-Z0-9_]+$ to make sure we are not having anything like foo_

137

It is a little awkward here because in the matcher, the regex use "::" to indicate matching start, but in llvm::regex it is the conventional "^". I will add some comments here.

Wizard updated this revision to Diff 131368.Jan 24 2018, 3:32 PM
Wizard marked an inline comment as done.

check for class extentsion

Wizard marked 7 inline comments as done.Jan 24 2018, 3:34 PM
Wizard added inline comments.
clang-tidy/objc/PropertyDeclarationCheck.cpp
137

End up using a bool since it is not about naming style but whether we are using it in matcher or normal regex match.

Wizard marked 2 inline comments as done.Jan 24 2018, 3:34 PM
hokein added inline comments.Jan 25 2018, 3:12 AM
clang-tidy/objc/PropertyDeclarationCheck.cpp
28

Please add documentation describing what these properties are.

57–58

Do we need to update the documentation here? it seems stale now?

88–96

Also add documentation for the method as well as parameters. It is a bit hard to follow the logic.

104

Does the comment still make sense? Seems you changed the regex below.

126

no need to pass const reference of llvm::StringRef. StringRef is cheap.

127

nit: use llvm::ArrayRef<std::string> would save a lot of keystroke.

129

we can use find_first_not_of or something similar.

160

Consider using const auto* CategoryDecl = dyn_cast<ObjCCategoryDecl*>(DeclContext), we can get rid of this cast, and NodeKind variable.

Wizard updated this revision to Diff 131511.Jan 25 2018, 2:18 PM
Wizard marked 8 inline comments as done.

update some documents and comments

clang-tidy/objc/PropertyDeclarationCheck.cpp
104

Yes they are actually the same. I am just replacing the prefix "::" with "^" according to the UsedInMatcher param.

126

The original property name I directly get from ast is a const. If I remove the const here, I will have to make a copy of the property name before calling this.
I prefer keep this const to save that copy :-)

160

Tried that before but I encountered 2 issues:

  1. 'clang::DeclContext' is not polymorphic
  2. cannot use dynamic_cast with -fno-rtti

which are preventing me from using dynamic_cast

hokein added inline comments.Jan 26 2018, 1:44 AM
clang-tidy/objc/PropertyDeclarationCheck.cpp
67

I think we save this code by using find_first_of and llvm::StringRef::tolower() function.

95

The same, ArrayRef.

121

The same: llvm::StringRef

126

Why? MatchedDecl->getName() returns llvm::StringRef. As the name indicates, StringRef is a const reference of String, using StringRef is sufficient.

The same to ArrayRef. So the function is like bool prefixedPropertyNameMatches(llvm::StringRef PropertyName, llvm::ArrayRef<std::string> Acronyms).

160

Sorry, I mean llvm::dyn_cast here, it should work.

163

Do we need it? I think you can pass SpecialAcronyms directly.

Wizard marked 3 inline comments as done.Jan 28 2018, 7:20 PM
Wizard added inline comments.
clang-tidy/objc/PropertyDeclarationCheck.cpp
121

Cannot remove the const for the same reason.

126

If I remove the const in the method, compiler will have error of "candidate function not viable: expects an l-value for 1st argument". I believe it cannot accept a const reference as arg if the definition is var.

160

It is not working either. It says "error: static_cast from 'clang::Decl *' to 'const clang::ObjCCategoryDecl *const *' is not allowed" though I have no idea why it is regarded as a static cast.
I am using it like this:
const auto *CategoryDecl = llvm::dyn_cast<const ObjCCategoryDecl *>(DeclContext);

Wizard updated this revision to Diff 131741.Jan 28 2018, 7:22 PM

resolve comments

benhamilton requested changes to this revision.Jan 29 2018, 9:45 AM
benhamilton added inline comments.
clang-tidy/objc/PropertyDeclarationCheck.cpp
126

I think hokein@ is saying you should change:

const llvm::StringRef &

to:

llvm::StringRef

Note removing both const and &, not just removing const. This is because there is no need to pass these by reference, they are already a reference.

Same with const llvm::ArrayRef &, it should just be llvm::ArrayRef.

132

No need to construct another llvm::StringRef(), StringRef::substr() returns a StringRef already.

160

You definitely don't want to use a C-style cast. My guess is adding const is not part of what dyn_cast<> does, so you can probably remove that from the dyn_cast<>. (You can of course assign to a const pointer if you want.)

This revision now requires changes to proceed.Jan 29 2018, 9:45 AM
Wizard updated this revision to Diff 131869.Jan 29 2018, 1:38 PM

resolve comments and fix some logic

benhamilton accepted this revision.Jan 29 2018, 1:50 PM
benhamilton added inline comments.
clang-tidy/objc/PropertyDeclarationCheck.cpp
129

Can you also check that Start + 1 < PropertyName.length() (e.g., the string doesn't end with a _)?

I know the regular expression shouldn't match this, so an assert is probably good. (There is logic later which tries to access Start + 1 without checking.)

135

Don't need to explicitly wrap in llvm::StringRef, that class has an implicit constructor from std::string.

https://github.com/llvm-mirror/llvm/blob/master/include/llvm/ADT/StringRef.h#L95

test/clang-tidy/objc-property-declaration.m
15–31

Can we add checks for properties whose names end with _?

This revision is now accepted and ready to land.Jan 29 2018, 1:50 PM
Wizard updated this revision to Diff 131877.Jan 29 2018, 2:27 PM
Wizard marked 2 inline comments as done.

add more tests

benhamilton accepted this revision.Jan 29 2018, 2:30 PM

Thanks!

Wizard marked 3 inline comments as done.Jan 29 2018, 2:32 PM
Wizard added inline comments.
clang-tidy/objc/PropertyDeclarationCheck.cpp
160

Finally figured out that I cannot put pointer type in dyn_cast<>. It needs to be "llvm::dyn_cast<ObjCCategoryDecl>(DeclContext)" even though DeclContext is a pointer. I have to say it is weird in C++...

163

It is not about acronyms but determine how to generate the fix. It will save me from checking the naming format again when generating the fix hint.

Wizard updated this revision to Diff 131904.Jan 29 2018, 5:08 PM

merge changes and add EscapedAcronyms to store the actual acronyms during runtime.

This revision was automatically updated to reflect the committed changes.
hokein added inline comments.Jan 31 2018, 1:33 AM
clang-tidy/objc/PropertyDeclarationCheck.cpp
126

Yeah, this is what I mean, thanks for the clarifying.

160

Yeah, llvm::dyn_cast doesn't need to specify the pointer, sorry for my beginning comment...