| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 #include "tools/gn/c_include_iterator.h" | 5 #include "tools/gn/c_include_iterator.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
| 9 #include "tools/gn/input_file.h" | 9 #include "tools/gn/input_file.h" |
| 10 #include "tools/gn/location.h" | 10 #include "tools/gn/location.h" |
| 11 | 11 |
| 12 namespace { | 12 namespace { |
| 13 | 13 |
| 14 enum IncludeType { | 14 enum IncludeType { |
| 15 INCLUDE_NONE, | 15 INCLUDE_NONE, |
| 16 INCLUDE_SYSTEM, // #include <...> | 16 INCLUDE_SYSTEM, // #include <...> |
| 17 INCLUDE_USER // #include "..." | 17 INCLUDE_USER // #include "..." |
| 18 }; | 18 }; |
| 19 | 19 |
| 20 // Returns true if str starts with the prefix. | |
| 21 bool StartsWith(const base::StringPiece& str, const base::StringPiece& prefix) { | |
| 22 base::StringPiece extracted = str.substr(0, prefix.size()); | |
| 23 return extracted == prefix; | |
| 24 } | |
| 25 | |
| 26 // Returns a new string piece referencing the same buffer as the argument, but | 20 // Returns a new string piece referencing the same buffer as the argument, but |
| 27 // with leading space trimmed. This only checks for space and tab characters | 21 // with leading space trimmed. This only checks for space and tab characters |
| 28 // since we're dealing with lines in C source files. | 22 // since we're dealing with lines in C source files. |
| 29 base::StringPiece TrimLeadingWhitespace(const base::StringPiece& str) { | 23 base::StringPiece TrimLeadingWhitespace(const base::StringPiece& str) { |
| 30 size_t new_begin = 0; | 24 size_t new_begin = 0; |
| 31 while (new_begin < str.size() && | 25 while (new_begin < str.size() && |
| 32 (str[new_begin] == ' ' || str[new_begin] == '\t')) | 26 (str[new_begin] == ' ' || str[new_begin] == '\t')) |
| 33 new_begin++; | 27 new_begin++; |
| 34 return str.substr(new_begin); | 28 return str.substr(new_begin); |
| 35 } | 29 } |
| 36 | 30 |
| 37 // We don't want to count comment lines and preprocessor lines toward our | 31 // We don't want to count comment lines and preprocessor lines toward our |
| 38 // "max lines to look at before giving up" since the beginnings of some files | 32 // "max lines to look at before giving up" since the beginnings of some files |
| 39 // may have a lot of comments. | 33 // may have a lot of comments. |
| 40 // | 34 // |
| 41 // We only handle C-style "//" comments since this is the normal commenting | 35 // We only handle C-style "//" comments since this is the normal commenting |
| 42 // style used in Chrome, and do so pretty stupidly. We don't want to write a | 36 // style used in Chrome, and do so pretty stupidly. We don't want to write a |
| 43 // full C++ parser here, we're just trying to get a good heuristic for checking | 37 // full C++ parser here, we're just trying to get a good heuristic for checking |
| 44 // the file. | 38 // the file. |
| 45 // | 39 // |
| 46 // We assume the line has leading whitespace trimmed. We also assume that empty | 40 // We assume the line has leading whitespace trimmed. We also assume that empty |
| 47 // lines have already been filtered out. | 41 // lines have already been filtered out. |
| 48 bool ShouldCountTowardNonIncludeLines(const base::StringPiece& line) { | 42 bool ShouldCountTowardNonIncludeLines(const base::StringPiece& line) { |
| 49 if (StartsWith(line, "//")) | 43 if (base::StartsWith(line, "//", base::CompareCase::SENSITIVE)) |
| 50 return false; // Don't count comments. | 44 return false; // Don't count comments. |
| 51 if (StartsWith(line, "/*") || StartsWith(line, " *")) | 45 if (base::StartsWith(line, "/*", base::CompareCase::SENSITIVE) || |
| 46 base::StartsWith(line, " *", base::CompareCase::SENSITIVE)) |
| 52 return false; // C-style comment blocks with stars along the left side. | 47 return false; // C-style comment blocks with stars along the left side. |
| 53 if (StartsWith(line, "#")) | 48 if (base::StartsWith(line, "#", base::CompareCase::SENSITIVE)) |
| 54 return false; // Don't count preprocessor. | 49 return false; // Don't count preprocessor. |
| 55 if (base::ContainsOnlyChars(line, base::kWhitespaceASCII)) | 50 if (base::ContainsOnlyChars(line, base::kWhitespaceASCII)) |
| 56 return false; // Don't count whitespace lines. | 51 return false; // Don't count whitespace lines. |
| 57 return true; // Count everything else. | 52 return true; // Count everything else. |
| 58 } | 53 } |
| 59 | 54 |
| 60 // Given a line, checks to see if it looks like an include or import and | 55 // Given a line, checks to see if it looks like an include or import and |
| 61 // extract the path. The type of include is returned. Returns INCLUDE_NONE on | 56 // extract the path. The type of include is returned. Returns INCLUDE_NONE on |
| 62 // error or if this is not an include line. | 57 // error or if this is not an include line. |
| 63 // | 58 // |
| 64 // The 1-based character number on the line that the include was found at | 59 // The 1-based character number on the line that the include was found at |
| 65 // will be filled into *begin_char. | 60 // will be filled into *begin_char. |
| 66 IncludeType ExtractInclude(const base::StringPiece& line, | 61 IncludeType ExtractInclude(const base::StringPiece& line, |
| 67 base::StringPiece* path, | 62 base::StringPiece* path, |
| 68 int* begin_char) { | 63 int* begin_char) { |
| 69 static const char kInclude[] = "#include"; | 64 static const char kInclude[] = "#include"; |
| 70 static const size_t kIncludeLen = arraysize(kInclude) - 1; // No null. | 65 static const size_t kIncludeLen = arraysize(kInclude) - 1; // No null. |
| 71 static const char kImport[] = "#import"; | 66 static const char kImport[] = "#import"; |
| 72 static const size_t kImportLen = arraysize(kImport) - 1; // No null. | 67 static const size_t kImportLen = arraysize(kImport) - 1; // No null. |
| 73 | 68 |
| 74 base::StringPiece trimmed = TrimLeadingWhitespace(line); | 69 base::StringPiece trimmed = TrimLeadingWhitespace(line); |
| 75 if (trimmed.empty()) | 70 if (trimmed.empty()) |
| 76 return INCLUDE_NONE; | 71 return INCLUDE_NONE; |
| 77 | 72 |
| 78 base::StringPiece contents; | 73 base::StringPiece contents; |
| 79 if (StartsWith(trimmed, base::StringPiece(kInclude, kIncludeLen))) | 74 if (base::StartsWith(trimmed, base::StringPiece(kInclude, kIncludeLen), |
| 75 base::CompareCase::SENSITIVE)) |
| 80 contents = TrimLeadingWhitespace(trimmed.substr(kIncludeLen)); | 76 contents = TrimLeadingWhitespace(trimmed.substr(kIncludeLen)); |
| 81 else if (StartsWith(trimmed, base::StringPiece(kImport, kImportLen))) | 77 else if (base::StartsWith(trimmed, base::StringPiece(kImport, kImportLen), |
| 78 base::CompareCase::SENSITIVE)) |
| 82 contents = TrimLeadingWhitespace(trimmed.substr(kImportLen)); | 79 contents = TrimLeadingWhitespace(trimmed.substr(kImportLen)); |
| 83 | 80 |
| 84 if (contents.empty()) | 81 if (contents.empty()) |
| 85 return INCLUDE_NONE; | 82 return INCLUDE_NONE; |
| 86 | 83 |
| 87 IncludeType type = INCLUDE_NONE; | 84 IncludeType type = INCLUDE_NONE; |
| 88 char terminating_char = 0; | 85 char terminating_char = 0; |
| 89 if (contents[0] == '"') { | 86 if (contents[0] == '"') { |
| 90 type = INCLUDE_USER; | 87 type = INCLUDE_USER; |
| 91 terminating_char = '"'; | 88 terminating_char = '"'; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 line_number_++; | 166 line_number_++; |
| 170 | 167 |
| 171 *line = file_.substr(begin, offset_ - begin); | 168 *line = file_.substr(begin, offset_ - begin); |
| 172 *line_number = line_number_; | 169 *line_number = line_number_; |
| 173 | 170 |
| 174 // If we didn't hit EOF, skip past the newline for the next one. | 171 // If we didn't hit EOF, skip past the newline for the next one. |
| 175 if (offset_ < file_.size()) | 172 if (offset_ < file_.size()) |
| 176 offset_++; | 173 offset_++; |
| 177 return true; | 174 return true; |
| 178 } | 175 } |
| OLD | NEW |