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.

Diff Detail

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
102–116

Instead of bool isCategory, how about an enum NamingStyle:

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

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

i < PropertyName.size() - 1

to

i < PropertyName.size()
139–141

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_]*$
156

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?

198

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
138

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

139–141

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_

156

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
156

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
29

Please add documentation describing what these properties are.

97–98

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

120–122

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

123

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

145

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

146

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

148

we can use find_first_not_of or something similar.

200

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
123

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

145

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 :-)

200

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
107

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

127

The same, ArrayRef.

140

The same: llvm::StringRef

145

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).

200

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

203

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
140

Cannot remove the const for the same reason.

145

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.

200

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
145

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.

151

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

200

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
148

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.)

154

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
19–35

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
200

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++...

203

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
145

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

200

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