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

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: unit test 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
« no previous file with comments | « tools/gn/c_include_iterator.h ('k') | tools/gn/c_include_iterator_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 enum IncludeType {
12 INCLUDE_NONE,
13 INCLUDE_SYSTEM, // #include <...>
14 INCLUDE_USER // #include "..."
15 };
16
17 // Returns true if str starts with the prefix.
18 bool StartsWith(const base::StringPiece& str, const base::StringPiece& prefix) {
19 base::StringPiece extracted = str.substr(0, prefix.size());
20 return extracted == prefix;
21 }
22
23 // Returns a new string piece referencing the same buffer as the argument, but
24 // with leading space trimmed. This only checks for space and tab characters
25 // since we're dealing with lines in C source files.
26 base::StringPiece TrimLeadingWhitespace(const base::StringPiece& str) {
27 size_t new_begin = 0;
28 while (new_begin < str.size() &&
29 (str[new_begin] == ' ' || str[new_begin] == '\t'))
30 new_begin++;
31 return str.substr(new_begin);
32 }
33
34 // We don't want to count comment lines and preprocessor lines toward our
35 // "max lines to look at before giving up" since the beginnings of some files
36 // may have a lot of comments.
37 //
38 // We only handle C-style "//" comments since this is the normal commenting
39 // style used in Chrome, and do so pretty stupidly. We don't want to write a
40 // full C++ parser here, we're just trying to get a good heuristic for checking
41 // the file.
42 //
43 // We assume the line has leading whitespace trimmed. We also assume that empty
44 // lines have already been filtered out.
45 bool ShouldCountTowardNonIncludeLines(const base::StringPiece& line) {
46 if (StartsWith(line, "//"))
47 return false; // Don't count comments.
48 if (StartsWith(line, "#"))
49 return false; // Don't count preprocessor.
50 return true; // Count everything else.
51 }
52
53 // Given a line, checks to see if it looks like an include or import and
54 // extract the path. The type of include is returned. Returns INCLUDE_NONE on
55 // error or if this is not an include line.
56 IncludeType ExtractInclude(const base::StringPiece& line,
57 base::StringPiece* path) {
58 static const char kInclude[] = "#include";
59 static const size_t kIncludeLen = arraysize(kInclude) - 1; // No null.
60 static const char kImport[] = "#import";
61 static const size_t kImportLen = arraysize(kImport) - 1; // No null.
62
63 base::StringPiece contents;
64 if (StartsWith(line, base::StringPiece(kInclude, kIncludeLen)))
65 contents = TrimLeadingWhitespace(line.substr(kIncludeLen));
66 else if (StartsWith(line, base::StringPiece(kImport, kImportLen)))
67 contents = TrimLeadingWhitespace(line.substr(kImportLen));
68
69 if (contents.empty())
70 return INCLUDE_NONE;
71
72 IncludeType type = INCLUDE_NONE;
73 char terminating_char = 0;
74 if (contents[0] == '"') {
75 type = INCLUDE_USER;
76 terminating_char = '"';
77 } else if (contents[0] == '<') {
78 type = INCLUDE_SYSTEM;
79 terminating_char = '>';
80 } else {
81 return INCLUDE_NONE;
82 }
83
84 // Count everything to next "/> as the contents.
85 size_t terminator_index = contents.find(terminating_char, 1);
86 if (terminator_index == base::StringPiece::npos)
87 return INCLUDE_NONE;
88
89 *path = contents.substr(1, terminator_index - 1);
90 return type;
91 }
92
93 } // namespace
94
95 const int CIncludeIterator::kMaxNonIncludeLines = 10;
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 lines_since_last_include_ = 0;
120 return true;
121 }
122
123 if (ShouldCountTowardNonIncludeLines(trimmed))
124 lines_since_last_include_++;
125 }
126 return false;
127 }
128
129 bool CIncludeIterator::GetNextLine(base::StringPiece* line) {
130 if (offset_ == file_.size())
131 return false;
132
133 size_t begin = offset_;
134 while (offset_ < file_.size() && file_[offset_] != '\n')
135 offset_++;
136
137 *line = file_.substr(begin, offset_ - begin);
138
139 // If we didn't hit EOF, skip past the newline for the next one.
140 if (offset_ < file_.size())
141 offset_++;
142 return true;
143 }
OLDNEW
« no previous file with comments | « tools/gn/c_include_iterator.h ('k') | tools/gn/c_include_iterator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698