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

Unified Diff: tools/gn/c_include_iterator.cc

Issue 216903004: Add optional public header checking to GN build (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: tools/gn/c_include_iterator.cc
diff --git a/tools/gn/c_include_iterator.cc b/tools/gn/c_include_iterator.cc
new file mode 100644
index 0000000000000000000000000000000000000000..214fbc2564b64bc77419177051b220ab8790291d
--- /dev/null
+++ b/tools/gn/c_include_iterator.cc
@@ -0,0 +1,142 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/c_include_iterator.h"
+
+#include "base/logging.h"
+
+namespace {
+
+const int kMaxNonIncludeLines = 10;
+
+enum IncludeType {
+ INCLUDE_NONE,
+ INCLUDE_SYSTEM, // #include <...>
+ INCLUDE_USER // #include "..."
+};
+
+// Returns true if str starts with the prefix.
+bool StartsWith(const base::StringPiece& str, const base::StringPiece& prefix) {
+ base::StringPiece extracted = str.substr(0, prefix.size());
+ return extracted == prefix;
+}
+
+// Returns a new string piece referencing the same buffer as the argument, but
+// with leading space trimmed. This only checks for space and tab characters
+// since we're dealing with lines in C source files.
+base::StringPiece TrimLeadingWhitespace(const base::StringPiece& str) {
+ size_t new_begin = 0;
+ while (new_begin < str.size() &&
+ (str[new_begin] == ' ' || str[new_begin] == '\t'))
+ new_begin++;
+ return str.substr(new_begin);
+}
+
+// We don't want to count comment lines and preprocessor lines toward our
+// "max lines to look at before giving up" since the beginnings of some files
+// may have a lot of comments.
+//
+// We on't handle C-style "//" comments since this is the normal commenting
scottmg 2014/04/05 00:40:07 "only"
+// style used in Chrome, and do so pretty stupidly. We don't want to write a
+// full C++ parser here, we're just trying to get a good heuristic for checking
+// the file.
+//
+// We assume the line has leading whitespace trimmed. We also assume that empty
+// lines have already been filtered out.
+bool ShouldCountTowardNonIncludeLines(const base::StringPiece& line) {
+ if (StartsWith(line, "//"))
+ return false; // Don't count comments.
+ if (StartsWith(line, "#"))
+ return false; // Don't count preprocessor.
+ return true; // Count everything else.
+}
+
+// Given a line, checks to see if it looks like an include or import and
+// extract the path. The type of include is returned. Returns INCLUDE_NONE on
+// error or if this is not an include line.
+IncludeType ExtractInclude(const base::StringPiece& line,
+ base::StringPiece* path) {
+ static const char kInclude[] = "#include";
+ static const size_t kIncludeLen = arraysize(kInclude) - 1; // No null.
+ static const char kImport[] = "#import";
+ static const size_t kImportLen = arraysize(kImport) - 1; // No null.
+
+ base::StringPiece contents;
+ if (StartsWith(line, base::StringPiece(kInclude, kIncludeLen)))
+ contents = TrimLeadingWhitespace(line.substr(kIncludeLen));
+ else if (StartsWith(line, base::StringPiece(kImport, kImportLen)))
+ contents = TrimLeadingWhitespace(line.substr(kImportLen));
+
+ if (contents.empty())
+ return INCLUDE_NONE;
+
+ IncludeType type = INCLUDE_NONE;
+ char terminating_char = 0;
+ if (contents[0] == '"') {
+ type = INCLUDE_USER;
+ terminating_char = '"';
+ } else if (contents[0] == '<') {
+ type = INCLUDE_SYSTEM;
+ terminating_char = '>';
+ } else {
+ return INCLUDE_NONE;
+ }
+
+ // Count everything to next "/> as the contents.
+ size_t terminator_index = contents.find(terminating_char, 1);
+ if (terminator_index == base::StringPiece::npos)
+ return INCLUDE_NONE;
+
+ *path = contents.substr(1, terminator_index - 1);
+ return type;
+}
+
+} // namespace
+
+CIncludeIterator::CIncludeIterator(const base::StringPiece& file)
+ : file_(file),
+ offset_(0),
+ lines_since_last_include_(0) {
+}
+
+CIncludeIterator::~CIncludeIterator() {
+}
+
+bool CIncludeIterator::GetNextIncludeString(base::StringPiece* out) {
+ base::StringPiece line;
+ while (lines_since_last_include_ < kMaxNonIncludeLines &&
+ GetNextLine(&line)) {
+ base::StringPiece trimmed = TrimLeadingWhitespace(line);
+ if (trimmed.empty())
+ continue; // Just ignore all empty lines.
+
+ base::StringPiece include_contents;
+ IncludeType type = ExtractInclude(trimmed, &include_contents);
+ if (type == INCLUDE_USER) {
+ // Only count user includes for now.
+ *out = include_contents;
+ return true;
+ }
+
+ if (ShouldCountTowardNonIncludeLines(trimmed))
+ lines_since_last_include_++;
scottmg 2014/04/05 00:40:07 needs to get reset, or renamed. and a test for thi
+ }
+ return false;
+}
+
+bool CIncludeIterator::GetNextLine(base::StringPiece* line) {
+ if (offset_ == file_.size())
+ return false;
+
+ size_t begin = offset_;
+ while (offset_ < file_.size() && file_[offset_] != '\n')
+ offset_++;
+
+ *line = file_.substr(begin, offset_ - begin);
+
+ // If we didn't hit EOF, skip past the newline for the next one.
+ if (offset_ < file_.size())
+ offset_++;
+ return true;
+}

Powered by Google App Engine
This is Rietveld 408576698