This is an archive of the discontinued LLVM Phabricator instance.

Add new check in google module for Objective-C code to ensure global variables follow the naming convention of Google Objective-C Style Guide
ClosedPublic

Authored by Wizard on Oct 27 2017, 2:33 PM.

Details

Summary

This is a new checker for objc files in clang-tidy.

The new check finds global variable declarations in Objective-C files that are not follow the pattern of variable names in Google's Objective-C Style Guide.

All the global variables should follow the pattern of "g[A-Z].*" (variables) or "k[A-Z].*" (constants). The check will suggest a variable name that follows the pattern
if it can be inferred from the original name.

Diff Detail

Repository
rL LLVM

Event Timeline

Wizard created this revision.Oct 27 2017, 2:33 PM
Wizard edited the summary of this revision. (Show Details)Oct 27 2017, 2:38 PM
Wizard added reviewers: benhamilton, hokein, alexfh.
Wizard set the repository for this revision to rL LLVM.

Check is really identifiers naming, so should have name like readability-identifier-naming. There are also google submodules, like google-readability, google-runtime, so will be good idea to add submodule for Objective-C.

docs/ReleaseNotes.rst
63 ↗(On Diff #120699)

No need for module name.

Wizard updated this revision to Diff 120771.Oct 29 2017, 11:06 PM
Wizard marked an inline comment as done.

update the check name to indicate that it is objc specific

hokein added inline comments.Oct 30 2017, 1:15 AM
clang-tidy/google/GlobalVariableDeclarationCheck.cpp
26 ↗(On Diff #120699)

Please make sure the patch follow the LLVM code style (https://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly).

For variable names, LLVM also uses Camel Case.

29 ↗(On Diff #120699)

Can you add a test for this case?

39 ↗(On Diff #120699)

Instead of constructing the new prefix, maybe construct a full new name, and replace the old name, this would also simplify the code below (so that you can use decl-getSourceRange).

52 ↗(On Diff #120699)

I think we need to filter out the source files, only allow the check to run on object-c files. You can use getLangOpts().

54 ↗(On Diff #120699)

Do we need to restrict to variable definitions (IsDefinition())?

69 ↗(On Diff #120699)

nit: I would use

if (const auto* VD = Result.Result.Nodes.getNodeAs<VarDecl>("global_var")) {
   ...
}
if (const auto* VD = XXX) {
   ...
}
clang-tidy/google/GoogleTidyModule.cpp
40 ↗(On Diff #120771)

We should put the check under clang::tidy::google::objc namespace.

41 ↗(On Diff #120771)

nit: sort in an alphabet order.

docs/clang-tidy/checks/google-global-variable-declaration.rst
7 ↗(On Diff #120699)

nit: would be nicer provide the link.

docs/clang-tidy/checks/google-objc-global-variable-declaration.rst
4 ↗(On Diff #120771)

nit: add missing ===

30 ↗(On Diff #120771)

I think we should have a newline at the end of the file, the same to the test.m file.

test/clang-tidy/google-global-variable-declaration.m
6 ↗(On Diff #120699)

nit: check the full code statement for fixes: static NSString* const kMConstString = @"hello";.

8 ↗(On Diff #120699)

Maybe add a test without static?

Wizard marked 4 inline comments as done.Oct 30 2017, 12:58 PM
Wizard added inline comments.
clang-tidy/google/GlobalVariableDeclarationCheck.cpp
29 ↗(On Diff #120699)

The test case of single character is added in line 12 of google-objc-global-variable-declaration.m

54 ↗(On Diff #120699)

I have thought about it. I think we should include non-definitions as well for now in order to check all cases.

Wizard updated this revision to Diff 120914.Oct 30 2017, 4:47 PM
Wizard marked 7 inline comments as done.

address comments

Wizard marked an inline comment as done.Oct 30 2017, 4:47 PM
Wizard added inline comments.
clang-tidy/google/GlobalVariableDeclarationCheck.cpp
39 ↗(On Diff #120699)

Done. But I played with it a little bit and had to avoid using decl-getSourceRange.
This method will return a range from the start of the type to the beginning of the init. E.g. for "static NSString* MyString = @"hi";" the substring of range will be "static NSString* MyString = @". It is pretty weird and will lead a result of replacement like 'kMyString"hi"'. With getLocation() + getName().size() it works well.

52 ↗(On Diff #120699)

I took a look at the getLangOpts(), but did not find any straight stuff to get the language type. Is there any trick about this?

Wizard marked 2 inline comments as done.Oct 31 2017, 11:22 AM
hokein added inline comments.Nov 2 2017, 2:22 AM
clang-tidy/google/GlobalVariableDeclarationCheck.cpp
39 ↗(On Diff #120699)

Oh, my bad. Thank for the clarification.

But still, we can use token range, CreateReplace(CharSourceRange::getTokenRange(SourceRange(Decl->getLocation()))) should work.

52 ↗(On Diff #120699)

The members are defined in llvm/tools/clang/include/clang/Basic/LangOptions.def. getLangOpts().ObjC1() or getLangOpts().ObjC2() should work (not sure the difference between ObjC1 and ObjC2).

54 ↗(On Diff #120699)

If this is expected, probably add a test case for it.

28 ↗(On Diff #120914)

There are still some code-style violations, e.g. fc, sc, the variable name should be CamelCase.

nit: I would use char here to make the type explicit.

29 ↗(On Diff #120914)

I'm a bit unclear here, are these exceptions? Are they stated in the code-style guideline?

docs/clang-tidy/checks/google-objc-global-variable-declaration.rst
10 ↗(On Diff #120914)
24 ↗(On Diff #120914)

The prefix of fix should be g, right? becasue this is not a constant.

test/clang-tidy/google-objc-global-variable-declaration.m
18 ↗(On Diff #120914)

Maybe use CHECK-FIXES: static NSString* a = @"too simple"; to make sure the check doesn't generate replacement., the same to the below case.

Wizard updated this revision to Diff 121367.Nov 2 2017, 1:58 PM
Wizard marked 8 inline comments as done.

Address comments. Adding language option check

Wizard added inline comments.Nov 2 2017, 2:00 PM
clang-tidy/google/GlobalVariableDeclarationCheck.cpp
29 ↗(On Diff #120914)

Generally we should never use a single-character name for global variables (it does not match our regex in the check of course). The special check here is because we don't wanna give a false hint that it should be 'kA' or something. The user need to decide a better name on their own.

Wizard marked 3 inline comments as done.Nov 2 2017, 2:00 PM
hokein edited edge metadata.Nov 3 2017, 1:58 AM

Thanks for the updates. The code looks mostly good, a few nits.

clang-tidy/google/GlobalVariableDeclarationCheck.cpp
29 ↗(On Diff #120914)

I see. it is worth a comment describing the purpose here.

44 ↗(On Diff #121367)

any reason why not using CharSourceRange::getTokenRange(SourceRange(Decl->getLocation())) here? Doesn't it work?

72 ↗(On Diff #121367)

nit: Not sure whether it is worth here, but I'd just remove it.

docs/clang-tidy/checks/google-objc-global-variable-declaration.rst
19 ↗(On Diff #121367)

nit: would be nicer to add a constant case here.

test/clang-tidy/google-objc-global-variable-declaration.m
22 ↗(On Diff #121367)

Check the full code statement.

Wizard updated this revision to Diff 121609.Nov 4 2017, 5:56 PM
Wizard marked 5 inline comments as done.

address comments

Wizard added inline comments.Nov 4 2017, 6:01 PM
clang-tidy/google/GlobalVariableDeclarationCheck.cpp
44 ↗(On Diff #121367)

Oh it works. I was looking at another constructor. So the getTokenRange can infer the length of the token given only the start location of the token?

Wizard marked an inline comment as done.Nov 4 2017, 6:02 PM
hokein accepted this revision.Nov 6 2017, 12:27 AM

LGTM.

clang-tidy/google/GlobalVariableDeclarationCheck.cpp
44 ↗(On Diff #121367)

yes, it returns the range of the token which the source location points to.

This revision is now accepted and ready to land.Nov 6 2017, 12:27 AM
This revision was automatically updated to reflect the committed changes.