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

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

Issue 2780113002: Refactor banned directory checking so Blink can opt into certain checks. (Closed)
Patch Set: better enum names Created 3 years, 8 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // A general interface for filtering and only acting on classes in Chromium C++ 5 // A general interface for filtering and only acting on classes in Chromium C++
6 // code. 6 // code.
7 7
8 #include "ChromeClassTester.h" 8 #include "ChromeClassTester.h"
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 30 matching lines...) Expand all
41 diagnostic_(instance.getDiagnostics()) { 41 diagnostic_(instance.getDiagnostics()) {
42 BuildBannedLists(); 42 BuildBannedLists();
43 } 43 }
44 44
45 ChromeClassTester::~ChromeClassTester() {} 45 ChromeClassTester::~ChromeClassTester() {}
46 46
47 void ChromeClassTester::CheckTag(TagDecl* tag) { 47 void ChromeClassTester::CheckTag(TagDecl* tag) {
48 // We handle class types here where we have semantic information. We can only 48 // We handle class types here where we have semantic information. We can only
49 // check structs/classes/enums here, but we get a bunch of nice semantic 49 // check structs/classes/enums here, but we get a bunch of nice semantic
50 // information instead of just parsing information. 50 // information instead of just parsing information.
51 if (InBannedNamespace(tag))
52 return;
53
54 SourceLocation location = tag->getInnerLocStart();
55 LocationType location_type = ClassifyLocation(location);
56 if (location_type == LocationType::kThirdParty)
57 return;
51 58
52 if (CXXRecordDecl* record = dyn_cast<CXXRecordDecl>(tag)) { 59 if (CXXRecordDecl* record = dyn_cast<CXXRecordDecl>(tag)) {
53 if (InBannedNamespace(record))
54 return;
55
56 SourceLocation record_location = record->getInnerLocStart();
57 if (InBannedDirectory(record_location))
58 return;
59
60 // We sadly need to maintain a blacklist of types that violate these 60 // We sadly need to maintain a blacklist of types that violate these
61 // rules, but do so for good reason or due to limitations of this 61 // rules, but do so for good reason or due to limitations of this
62 // checker (i.e., we don't handle extern templates very well). 62 // checker (i.e., we don't handle extern templates very well).
63 std::string base_name = record->getNameAsString(); 63 std::string base_name = record->getNameAsString();
64 if (IsIgnoredType(base_name)) 64 if (IsIgnoredType(base_name))
65 return; 65 return;
66 66
67 // We ignore all classes that end with "Matcher" because they're probably 67 // We ignore all classes that end with "Matcher" because they're probably
68 // GMock artifacts. 68 // GMock artifacts.
69 if (ends_with(base_name, "Matcher")) 69 if (ends_with(base_name, "Matcher"))
70 return; 70 return;
71 71
72 CheckChromeClass(record_location, record); 72 CheckChromeClass(location_type, location, record);
73 } else if (EnumDecl* enum_decl = dyn_cast<EnumDecl>(tag)) { 73 } else if (EnumDecl* enum_decl = dyn_cast<EnumDecl>(tag)) {
74 SourceLocation enum_location = enum_decl->getInnerLocStart();
75 if (InBannedDirectory(enum_location))
76 return;
77
78 std::string base_name = enum_decl->getNameAsString(); 74 std::string base_name = enum_decl->getNameAsString();
75 // TODO(dcheng): This should probably consult a separate list.
79 if (IsIgnoredType(base_name)) 76 if (IsIgnoredType(base_name))
80 return; 77 return;
81 78
82 CheckChromeEnum(enum_location, enum_decl); 79 CheckChromeEnum(location_type, location, enum_decl);
83 } 80 }
84 } 81 }
85 82
86 void ChromeClassTester::emitWarning(SourceLocation loc, 83 void ChromeClassTester::emitWarning(SourceLocation loc,
87 const char* raw_error) { 84 const char* raw_error) {
88 FullSourceLoc full(loc, instance().getSourceManager()); 85 FullSourceLoc full(loc, instance().getSourceManager());
89 std::string err; 86 std::string err;
90 err = "[chromium-style] "; 87 err = "[chromium-style] ";
91 err += raw_error; 88 err += raw_error;
92 89
93 DiagnosticIDs::Level level = getErrorLevel() == DiagnosticsEngine::Error 90 DiagnosticIDs::Level level = getErrorLevel() == DiagnosticsEngine::Error
94 ? DiagnosticIDs::Error : DiagnosticIDs::Warning; 91 ? DiagnosticIDs::Error : DiagnosticIDs::Warning;
95 92
96 unsigned id = diagnostic().getDiagnosticIDs()->getCustomDiagID(level, err); 93 unsigned id = diagnostic().getDiagnosticIDs()->getCustomDiagID(level, err);
97 DiagnosticBuilder builder = diagnostic().Report(full, id); 94 DiagnosticBuilder builder = diagnostic().Report(full, id);
98 95
99 } 96 }
100 97
101 bool ChromeClassTester::InBannedDirectory(SourceLocation loc) { 98 ChromeClassTester::LocationType ChromeClassTester::ClassifyLocation(
99 SourceLocation loc) {
102 if (instance().getSourceManager().isInSystemHeader(loc)) 100 if (instance().getSourceManager().isInSystemHeader(loc))
103 return true; 101 return LocationType::kThirdParty;
104 102
105 std::string filename; 103 std::string filename;
106 if (!GetFilename(loc, &filename)) { 104 if (!GetFilename(loc, &filename)) {
107 // If the filename cannot be determined, simply treat this as a banned 105 // If the filename cannot be determined, simply treat this as a banned
108 // location, instead of going through the full lookup process. 106 // location, instead of going through the full lookup process.
109 return true; 107 return LocationType::kThirdParty;
110 } 108 }
111 109
112 // We need to special case scratch space; which is where clang does its 110 // We need to special case scratch space; which is where clang does its
113 // macro expansion. We explicitly want to allow people to do otherwise bad 111 // macro expansion. We explicitly want to allow people to do otherwise bad
114 // things through macros that were defined due to third party libraries. 112 // things through macros that were defined due to third party libraries.
115 if (filename == "<scratch space>") 113 if (filename == "<scratch space>")
116 return true; 114 return LocationType::kThirdParty;
117 115
118 // Don't complain about autogenerated protobuf files. 116 // Don't complain about autogenerated protobuf files.
119 if (ends_with(filename, ".pb.h")) { 117 if (ends_with(filename, ".pb.h"))
120 return true; 118 return LocationType::kThirdParty;
121 }
122 119
123 #if defined(LLVM_ON_UNIX) 120 #if defined(LLVM_ON_UNIX)
124 // Resolve the symlinktastic relative path and make it absolute. 121 // Resolve the symlinktastic relative path and make it absolute.
125 char resolvedPath[MAXPATHLEN]; 122 char resolvedPath[MAXPATHLEN];
126 if (options_.no_realpath) { 123 if (options_.no_realpath) {
127 // Same reason as windows below, but we don't need to do 124 // Same reason as windows below, but we don't need to do
128 // the '\\' manipulation on linux. 125 // the '\\' manipulation on linux.
129 filename.insert(filename.begin(), '/'); 126 filename.insert(filename.begin(), '/');
130 } else if (realpath(filename.c_str(), resolvedPath)) { 127 } else if (realpath(filename.c_str(), resolvedPath)) {
131 filename = resolvedPath; 128 filename = resolvedPath;
(...skipping 21 matching lines...) Expand all
153 size_needed = WideCharToMultiByte(CP_UTF8, 0, full_utf16.data(), -1, 150 size_needed = WideCharToMultiByte(CP_UTF8, 0, full_utf16.data(), -1,
154 nullptr, 0, nullptr, nullptr); 151 nullptr, 0, nullptr, nullptr);
155 filename.resize(size_needed); 152 filename.resize(size_needed);
156 WideCharToMultiByte(CP_UTF8, 0, full_utf16.data(), -1, &filename[0], 153 WideCharToMultiByte(CP_UTF8, 0, full_utf16.data(), -1, &filename[0],
157 size_needed, nullptr, nullptr); 154 size_needed, nullptr, nullptr);
158 } 155 }
159 156
160 std::replace(filename.begin(), filename.end(), '\\', '/'); 157 std::replace(filename.begin(), filename.end(), '\\', '/');
161 #endif 158 #endif
162 159
163 for (const std::string& allowed_dir : allowed_directories_) { 160 for (const std::string& blink_dir : blink_directories_) {
164 // If any of the allowed directories occur as a component in filename, 161 // If any of the allowed directories occur as a component in filename,
165 // this file is allowed. 162 // this file is allowed.
166 assert(allowed_dir.front() == '/' && "Allowed dir must start with '/'"); 163 assert(blink_dir.front() == '/' && "Allowed dir must start with '/'");
167 assert(allowed_dir.back() == '/' && "Allowed dir must end with '/'"); 164 assert(blink_dir.back() == '/' && "Allowed dir must end with '/'");
168 165
169 if (filename.find(allowed_dir) != std::string::npos) 166 if (filename.find(blink_dir) != std::string::npos)
170 return false; 167 return LocationType::kBlink;
171 } 168 }
172 169
173 for (const std::string& banned_dir : banned_directories_) { 170 for (const std::string& banned_dir : banned_directories_) {
174 // If any of the banned directories occur as a component in filename, 171 // If any of the banned directories occur as a component in filename,
175 // this file is rejected. 172 // this file is rejected.
176 assert(banned_dir.front() == '/' && "Banned dir must start with '/'"); 173 assert(banned_dir.front() == '/' && "Banned dir must start with '/'");
177 assert(banned_dir.back() == '/' && "Banned dir must end with '/'"); 174 assert(banned_dir.back() == '/' && "Banned dir must end with '/'");
178 175
179 if (filename.find(banned_dir) != std::string::npos) 176 if (filename.find(banned_dir) != std::string::npos)
180 return true; 177 return LocationType::kThirdParty;
181 } 178 }
182 179
183 return false; 180 return LocationType::kChrome;
184 } 181 }
185 182
186 bool ChromeClassTester::InBannedNamespace(const Decl* record) { 183 bool ChromeClassTester::InBannedNamespace(const Decl* record) {
187 std::string n = GetNamespace(record); 184 std::string n = GetNamespace(record);
188 if (!n.empty()) { 185 if (!n.empty())
189 return std::find(banned_namespaces_.begin(), banned_namespaces_.end(), n) 186 return banned_namespaces_.find(n) != banned_namespaces_.end();
190 != banned_namespaces_.end();
191 }
192 187
193 return false; 188 return false;
194 } 189 }
195 190
196 std::string ChromeClassTester::GetNamespace(const Decl* record) { 191 std::string ChromeClassTester::GetNamespace(const Decl* record) {
197 return GetNamespaceImpl(record->getDeclContext(), ""); 192 return GetNamespaceImpl(record->getDeclContext(), std::string());
198 } 193 }
199 194
200 bool ChromeClassTester::HasIgnoredBases(const CXXRecordDecl* record) { 195 bool ChromeClassTester::HasIgnoredBases(const CXXRecordDecl* record) {
201 for (const auto& base : record->bases()) { 196 for (const auto& base : record->bases()) {
202 CXXRecordDecl* base_record = base.getType()->getAsCXXRecordDecl(); 197 CXXRecordDecl* base_record = base.getType()->getAsCXXRecordDecl();
203 if (!base_record) 198 if (!base_record)
204 continue; 199 continue;
205 200
206 const std::string& base_name = base_record->getQualifiedNameAsString(); 201 const std::string& base_name = base_record->getQualifiedNameAsString();
207 if (ignored_base_classes_.count(base_name) > 0) 202 if (ignored_base_classes_.count(base_name) > 0)
(...skipping 23 matching lines...) Expand all
231 source_manager.getImmediateExpansionRange(record_location).first; 226 source_manager.getImmediateExpansionRange(record_location).first;
232 } 227 }
233 228
234 return false; 229 return false;
235 } 230 }
236 231
237 void ChromeClassTester::BuildBannedLists() { 232 void ChromeClassTester::BuildBannedLists() {
238 banned_namespaces_.emplace("std"); 233 banned_namespaces_.emplace("std");
239 banned_namespaces_.emplace("__gnu_cxx"); 234 banned_namespaces_.emplace("__gnu_cxx");
240 235
241 if (options_.enforce_in_thirdparty_webkit) { 236 blink_directories_.emplace("/third_party/WebKit/");
242 allowed_directories_.emplace("/third_party/WebKit/");
243 }
244 237
245 banned_directories_.emplace("/third_party/"); 238 banned_directories_.emplace("/third_party/");
246 banned_directories_.emplace("/native_client/"); 239 banned_directories_.emplace("/native_client/");
247 banned_directories_.emplace("/breakpad/"); 240 banned_directories_.emplace("/breakpad/");
248 banned_directories_.emplace("/courgette/"); 241 banned_directories_.emplace("/courgette/");
249 banned_directories_.emplace("/ppapi/"); 242 banned_directories_.emplace("/ppapi/");
250 banned_directories_.emplace("/testing/"); 243 banned_directories_.emplace("/testing/");
251 banned_directories_.emplace("/v8/"); 244 banned_directories_.emplace("/v8/");
252 banned_directories_.emplace("/sdch/"); 245 banned_directories_.emplace("/sdch/");
253 banned_directories_.emplace("/frameworks/"); 246 banned_directories_.emplace("/frameworks/");
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 } 334 }
342 335
343 *filename = ploc.getFilename(); 336 *filename = ploc.getFilename();
344 return true; 337 return true;
345 } 338 }
346 339
347 DiagnosticsEngine::Level ChromeClassTester::getErrorLevel() { 340 DiagnosticsEngine::Level ChromeClassTester::getErrorLevel() {
348 return diagnostic().getWarningsAsErrors() ? DiagnosticsEngine::Error 341 return diagnostic().getWarningsAsErrors() ? DiagnosticsEngine::Error
349 : DiagnosticsEngine::Warning; 342 : DiagnosticsEngine::Warning;
350 } 343 }
OLDNEW
« no previous file with comments | « tools/clang/plugins/ChromeClassTester.h ('k') | tools/clang/plugins/FindBadConstructsConsumer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698