Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: tools/clang/plugins/ChromeClassTester.cpp

Issue 6368055: Commit my clang plugin and fix up documentation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Moved to clang/plugins/ Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // A general interface for filtering and only acting on classes in Chromium C++
6 // code.
7
8 #include "ChromeClassTester.h"
9
10 #include "clang/Basic/FileManager.h"
11
12 using namespace clang;
13
14 namespace {
15
16 bool starts_with(const std::string& one, const std::string& two) {
17 return one.substr(0, two.size()) == two;
18 }
19
20 bool ends_with(const std::string& one, const std::string& two) {
21 return one.substr(one.size() - two.size(), two.size()) == two;
22 }
23
24 } // namespace
25
26 ChromeClassTester::ChromeClassTester(CompilerInstance& instance)
27 : instance_(instance),
28 d_(instance.getDiagnostics()) {
29 // TODO: Ignore a user configurable list of toplevel namespaces, not just
30 // these hardcoded ones.
31 banned_namespaces_.push_back("std");
32 banned_namespaces_.push_back("__gnu_cxx");
33
34 // TODO: Let the user configure this list of directories.
Nico 2011/02/02 23:13:06 i think this todo and the one before can just be d
35 banned_directories_.push_back("third_party");
36 banned_directories_.push_back("native_client");
37 banned_directories_.push_back("breakpad");
38 banned_directories_.push_back("courgette");
39 banned_directories_.push_back("ppapi");
40 banned_directories_.push_back("/usr");
41 banned_directories_.push_back("testing");
42 banned_directories_.push_back("googleurl");
43 banned_directories_.push_back("v8");
44 banned_directories_.push_back("sdch");
45
46 // You are standing in a mazy of twisty dependencies, all resolved by
47 // putting everything in the header.
48 banned_directories_.push_back("chrome/test/automation");
49
50 // TODO: Confurgre this some other way.
Nico 2011/02/02 23:13:06 "Configure"?
51 ignored_record_names_.push_back("ThreadLocalBoolean");
52
53 // A complicated pickle derived struct that is all packed integers.
54 ignored_record_names_.push_back("Header");
55
56 // Part of the GPU system that uses multiple included header
57 // weirdness. Never getting this right.
58 ignored_record_names_.push_back("Validators");
59
60 // RAII class that's simple enough (media/base/callback.h).
61 ignored_record_names_.push_back("AutoTaskRunner");
62 ignored_record_names_.push_back("AutoCallbackRunner");
63
64 // Part of our public interface that nacl and friends use. (Arguably, this
65 // should mean that this is a higher priority but fixing this looks hard.)
66 ignored_record_names_.push_back("PluginVersionInfo");
67 }
68
69 ChromeClassTester::~ChromeClassTester() {}
70
71 void ChromeClassTester::HandleTagDeclDefinition(TagDecl* tag) {
72 if (CXXRecordDecl* record = dyn_cast<CXXRecordDecl>(tag)) {
73 // If this is a POD or a class template or a type dependent on a
74 // templated class, assume there's no ctor/dtor/virtual method
75 // optimization that we can do.
76 if (record->isPOD() ||
77 record->getDescribedClassTemplate() ||
78 record->getTemplateSpecializationKind() ||
79 record->isDependentType())
80 return;
81
82 if (InBannedNamespace(record))
83 return;
84
85 SourceLocation record_location = record->getInnerLocStart();
86 if (InBannedDirectory(record_location))
87 return;
88
89 // For now, due to large amounts of inlining in our unit test code, there's
90 // no way in hell we'll pass our checks but we want to deploy clang plugins
91 // now.
Nico 2011/02/02 23:13:06 TODO? Seems like inlining in test code is what's s
92 if (IsTestCode(record)) {
93 return;
94 }
95
96 // We sadly need to maintain a blacklist of types that violate these
97 // rules, but do so for good reason or due to limitations of this
98 // checker (i.e., we don't handle extern templates very well).
99 if (IsIgnoredType(record))
100 return;
101
102 CheckChromeClass(record_location, record);
103 }
104 }
105
106 void ChromeClassTester::emitWarning(SourceLocation loc, const char* raw_error) {
107 FullSourceLoc full(loc, instance().getSourceManager());
108 std::string err;
109 err = "[chrome-style] ";
110 err += raw_error;
111 unsigned id = diagnostic().getCustomDiagID(Diagnostic::Warning, err);
112 DiagnosticBuilder B = diagnostic().Report(full, id);
113 }
114
115 bool ChromeClassTester::IsTestCode(Decl* record) {
116 if (instance_.hasSourceManager()) {
117 SourceManager& m = instance_.getSourceManager();
118 std::string name = m.getFileEntryForID(m.getMainFileID())->getName();
119 return name.find("test") != name.npos ||
120 name.find("mock") != name.npos;
121 }
122 return false;
123 }
124
125 bool ChromeClassTester::InBannedNamespace(Decl* record) {
126 std::string n = GetNamespace(record);
127 if (n != "") {
128 return std::find(banned_namespaces_.begin(), banned_namespaces_.end(), n)
129 != banned_namespaces_.end();
130 }
131
132 return false;
133 }
134
135 std::string ChromeClassTester::GetNamespace(Decl* record) {
136 return GetNamespaceImpl(record->getDeclContext(), "");
137 }
138
139 std::string ChromeClassTester::GetNamespaceImpl(const DeclContext* context,
140 std::string candidate) {
141 switch (context->getDeclKind()) {
142 case Decl::TranslationUnit: {
143 return candidate;
144 }
145 case Decl::Namespace: {
146 const NamespaceDecl* decl = dyn_cast<NamespaceDecl>(context);
147 std::string name_str;
148 llvm::raw_string_ostream OS(name_str);
149 if (decl->isAnonymousNamespace())
150 OS << "<anonymous namespace>";
151 else
152 OS << decl;
153 return GetNamespaceImpl(context->getParent(),
154 OS.str());
155 }
156 default: {
157 return GetNamespaceImpl(context->getParent(), candidate);
158 }
159 }
160 }
161
162 bool ChromeClassTester::InBannedDirectory(const SourceLocation& loc) {
163 if (loc.isFileID() && loc.isValid()) {
164 bool invalid = false;
165 const char* buffer_name = instance_.getSourceManager().getBufferName(
166 loc, &invalid);
167 if (!invalid && buffer_name) {
168 // TODO: Un-hard code these values and make them specifiable on the
169 // command line.
Nico 2011/02/02 23:13:06 why?
170 std::string b(buffer_name);
171
172 // Don't complain about these things in implementation files.
173 if (ends_with(b, ".cc") || ends_with(b, ".cpp")) {
174 return true;
175 }
176
177 // Don't complain about autogenerated protobuf files.
178 if (ends_with(b, ".pb.h")) {
179 return true;
180 }
181
182 // Strip preceding path crap.
183 if (starts_with(b, "./"))
184 b = b.substr(2);
185
186 for (std::vector<std::string>::const_iterator it =
187 banned_directories_.begin();
188 it != banned_directories_.end(); ++it) {
189 if (starts_with(b, *it))
190 return true;
191 }
192 }
193 }
194
195 return false;
196 }
197
198 bool ChromeClassTester::IsIgnoredType(RecordDecl* record) {
199 std::string base_name = record->getNameAsString();
200 for (std::vector<std::string>::const_iterator it =
201 ignored_record_names_.begin();
202 it != ignored_record_names_.end(); ++it) {
203 if (base_name == *it)
204 return true;
205 }
206
207 return false;
208 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698