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

Side by Side 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, 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 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 #include "tools/gn/c_include_iterator.h"
6
7 #include "base/logging.h"
8
9 namespace {
10
11 const int kMaxNonIncludeLines = 10;
12
13 enum IncludeType {
14 INCLUDE_NONE,
15 INCLUDE_SYSTEM, // #include <...>
16 INCLUDE_USER // #include "..."
17 };
18
19 // Returns true if str starts with the prefix.
20 bool StartsWith(const base::StringPiece& str, const base::StringPiece& prefix) {
21 base::StringPiece extracted = str.substr(0, prefix.size());
22 return extracted == prefix;
23 }
24
25 // Returns a new string piece referencing the same buffer as the argument, but
26 // with leading space trimmed. This only checks for space and tab characters
27 // since we're dealing with lines in C source files.
28 base::StringPiece TrimLeadingWhitespace(const base::StringPiece& str) {
29 size_t new_begin = 0;
30 while (new_begin < str.size() &&
31 (str[new_begin] == ' ' || str[new_begin] == '\t'))
32 new_begin++;
33 return str.substr(new_begin);
34 }
35
36 // We don't want to count comment lines and preprocessor lines toward our
37 // "max lines to look at before giving up" since the beginnings of some files
38 // may have a lot of comments.
39 //
40 // We on't handle C-style "//" comments since this is the normal commenting
scottmg 2014/04/05 00:40:07 "only"
41 // style used in Chrome, and do so pretty stupidly. We don't want to write a
42 // full C++ parser here, we're just trying to get a good heuristic for checking
43 // the file.
44 //
45 // We assume the line has leading whitespace trimmed. We also assume that empty
46 // lines have already been filtered out.
47 bool ShouldCountTowardNonIncludeLines(const base::StringPiece& line) {
48 if (StartsWith(line, "//"))
49 return false; // Don't count comments.
50 if (StartsWith(line, "#"))
51 return false; // Don't count preprocessor.
52 return true; // Count everything else.
53 }
54
55 // Given a line, checks to see if it looks like an include or import and
56 // extract the path. The type of include is returned. Returns INCLUDE_NONE on
57 // error or if this is not an include line.
58 IncludeType ExtractInclude(const base::StringPiece& line,
59 base::StringPiece* path) {
60 static const char kInclude[] = "#include";
61 static const size_t kIncludeLen = arraysize(kInclude) - 1; // No null.
62 static const char kImport[] = "#import";
63 static const size_t kImportLen = arraysize(kImport) - 1; // No null.
64
65 base::StringPiece contents;
66 if (StartsWith(line, base::StringPiece(kInclude, kIncludeLen)))
67 contents = TrimLeadingWhitespace(line.substr(kIncludeLen));
68 else if (StartsWith(line, base::StringPiece(kImport, kImportLen)))
69 contents = TrimLeadingWhitespace(line.substr(kImportLen));
70
71 if (contents.empty())
72 return INCLUDE_NONE;
73
74 IncludeType type = INCLUDE_NONE;
75 char terminating_char = 0;
76 if (contents[0] == '"') {
77 type = INCLUDE_USER;
78 terminating_char = '"';
79 } else if (contents[0] == '<') {
80 type = INCLUDE_SYSTEM;
81 terminating_char = '>';
82 } else {
83 return INCLUDE_NONE;
84 }
85
86 // Count everything to next "/> as the contents.
87 size_t terminator_index = contents.find(terminating_char, 1);
88 if (terminator_index == base::StringPiece::npos)
89 return INCLUDE_NONE;
90
91 *path = contents.substr(1, terminator_index - 1);
92 return type;
93 }
94
95 } // namespace
96
97 CIncludeIterator::CIncludeIterator(const base::StringPiece& file)
98 : file_(file),
99 offset_(0),
100 lines_since_last_include_(0) {
101 }
102
103 CIncludeIterator::~CIncludeIterator() {
104 }
105
106 bool CIncludeIterator::GetNextIncludeString(base::StringPiece* out) {
107 base::StringPiece line;
108 while (lines_since_last_include_ < kMaxNonIncludeLines &&
109 GetNextLine(&line)) {
110 base::StringPiece trimmed = TrimLeadingWhitespace(line);
111 if (trimmed.empty())
112 continue; // Just ignore all empty lines.
113
114 base::StringPiece include_contents;
115 IncludeType type = ExtractInclude(trimmed, &include_contents);
116 if (type == INCLUDE_USER) {
117 // Only count user includes for now.
118 *out = include_contents;
119 return true;
120 }
121
122 if (ShouldCountTowardNonIncludeLines(trimmed))
123 lines_since_last_include_++;
scottmg 2014/04/05 00:40:07 needs to get reset, or renamed. and a test for thi
124 }
125 return false;
126 }
127
128 bool CIncludeIterator::GetNextLine(base::StringPiece* line) {
129 if (offset_ == file_.size())
130 return false;
131
132 size_t begin = offset_;
133 while (offset_ < file_.size() && file_[offset_] != '\n')
134 offset_++;
135
136 *line = file_.substr(begin, offset_ - begin);
137
138 // If we didn't hit EOF, skip past the newline for the next one.
139 if (offset_ < file_.size())
140 offset_++;
141 return true;
142 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698