Line data Source code
1 : // Copyright 2017 the V8 project 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 <algorithm>
6 : #include <fstream>
7 : #include <iostream>
8 : #include <string>
9 :
10 : #include "src/base/logging.h"
11 : #include "src/torque/ast.h"
12 : #include "src/torque/utils.h"
13 :
14 : namespace v8 {
15 : namespace internal {
16 : namespace torque {
17 :
18 327 : std::string StringLiteralUnquote(const std::string& s) {
19 : DCHECK(('"' == s.front() && '"' == s.back()) ||
20 : ('\'' == s.front() && '\'' == s.back()));
21 327 : std::stringstream result;
22 9636 : for (size_t i = 1; i < s.length() - 1; ++i) {
23 4491 : if (s[i] == '\\') {
24 0 : switch (s[++i]) {
25 : case 'n':
26 : result << '\n';
27 : break;
28 : case 'r':
29 : result << '\r';
30 : break;
31 : case 't':
32 : result << '\t';
33 : break;
34 : case '\'':
35 : case '"':
36 : case '\\':
37 : result << s[i];
38 : break;
39 : default:
40 0 : UNREACHABLE();
41 : }
42 : } else {
43 : result << s[i];
44 : }
45 : }
46 327 : return result.str();
47 : }
48 :
49 563 : std::string StringLiteralQuote(const std::string& s) {
50 563 : std::stringstream result;
51 : result << '"';
52 39242 : for (size_t i = 0; i < s.length(); ++i) {
53 19058 : switch (s[i]) {
54 : case '\n':
55 0 : result << "\\n";
56 0 : break;
57 : case '\r':
58 0 : result << "\\r";
59 0 : break;
60 : case '\t':
61 0 : result << "\\t";
62 0 : break;
63 : case '\'':
64 : case '"':
65 : case '\\':
66 218 : result << "\\" << s[i];
67 : break;
68 : default:
69 : result << s[i];
70 : }
71 : }
72 : result << '"';
73 563 : return result.str();
74 : }
75 :
76 0 : std::string CurrentPositionAsString() {
77 0 : return PositionAsString(CurrentSourcePosition::Get());
78 : }
79 :
80 4 : DEFINE_CONTEXTUAL_VARIABLE(LintErrorStatus)
81 :
82 0 : [[noreturn]] void ReportErrorString(const std::string& error) {
83 0 : std::cerr << CurrentPositionAsString() << ": Torque error: " << error << "\n";
84 0 : v8::base::OS::Abort();
85 : }
86 :
87 0 : void LintError(const std::string& error) {
88 : LintErrorStatus::SetLintError();
89 0 : std::cerr << CurrentPositionAsString() << ": Lint error: " << error << "\n";
90 0 : }
91 :
92 0 : void NamingConventionError(const std::string& type, const std::string& name,
93 : const std::string& convention) {
94 0 : std::stringstream sstream;
95 0 : sstream << type << " \"" << name << "\" doesn't follow \"" << convention
96 0 : << "\" naming convention.";
97 0 : LintError(sstream.str());
98 0 : }
99 :
100 : namespace {
101 :
102 2890 : bool ContainsUnderscore(const std::string& s) {
103 2890 : if (s.empty()) return false;
104 2890 : return s.find("_") != std::string::npos;
105 : }
106 :
107 26 : bool ContainsUpperCase(const std::string& s) {
108 26 : if (s.empty()) return false;
109 264 : return std::any_of(s.begin(), s.end(), [](char c) { return isupper(c); });
110 : }
111 :
112 : // Torque has some namespace constants that are used like language level
113 : // keywords, e.g.: 'True', 'Undefined', etc.
114 : // These do not need to follow the default naming convention for constants.
115 : bool IsKeywordLikeName(const std::string& s) {
116 : static const char* const keyword_like_constants[]{"True", "False", "Hole",
117 : "Null", "Undefined"};
118 :
119 : return std::find(std::begin(keyword_like_constants),
120 : std::end(keyword_like_constants),
121 : s) != std::end(keyword_like_constants);
122 : }
123 :
124 : // Untagged/MachineTypes like 'int32', 'intptr' etc. follow a 'all-lowercase'
125 : // naming convention and are those exempt from the normal type convention.
126 : bool IsMachineType(const std::string& s) {
127 : static const char* const machine_types[]{
128 : "void", "never", "int8", "uint8", "int16", "uint16",
129 : "int31", "uint31", "int32", "uint32", "int64", "intptr",
130 : "uintptr", "float32", "float64", "bool", "string", "bint"};
131 :
132 : return std::find(std::begin(machine_types), std::end(machine_types), s) !=
133 : std::end(machine_types);
134 : }
135 :
136 : } // namespace
137 :
138 2136 : bool IsLowerCamelCase(const std::string& s) {
139 2136 : if (s.empty()) return false;
140 2136 : return islower(s[0]) && !ContainsUnderscore(s);
141 : }
142 :
143 754 : bool IsUpperCamelCase(const std::string& s) {
144 754 : if (s.empty()) return false;
145 754 : return isupper(s[0]) && !ContainsUnderscore(s);
146 : }
147 :
148 26 : bool IsSnakeCase(const std::string& s) {
149 26 : if (s.empty()) return false;
150 26 : return !ContainsUpperCase(s);
151 : }
152 :
153 24 : bool IsValidNamespaceConstName(const std::string& s) {
154 24 : if (s.empty()) return false;
155 24 : if (IsKeywordLikeName(s)) return true;
156 :
157 38 : return s[0] == 'k' && IsUpperCamelCase(s.substr(1));
158 : }
159 :
160 106 : bool IsValidTypeName(const std::string& s) {
161 106 : if (s.empty()) return false;
162 106 : if (IsMachineType(s)) return true;
163 :
164 88 : return IsUpperCamelCase(s);
165 : }
166 :
167 20 : std::string CapifyStringWithUnderscores(const std::string& camellified_string) {
168 : std::string result;
169 : bool previousWasLower = false;
170 338 : for (auto current : camellified_string) {
171 298 : if (previousWasLower && isupper(current)) {
172 : result += "_";
173 : }
174 298 : result += toupper(current);
175 298 : previousWasLower = (islower(current));
176 : }
177 20 : return result;
178 : }
179 :
180 2641 : std::string CamelifyString(const std::string& underscore_string) {
181 : std::string result;
182 : bool word_beginning = true;
183 21237 : for (auto current : underscore_string) {
184 15955 : if (current == '_' || current == '-') {
185 : word_beginning = true;
186 : continue;
187 : }
188 15485 : if (word_beginning) {
189 3111 : current = toupper(current);
190 : }
191 : result += current;
192 : word_beginning = false;
193 : }
194 2641 : return result;
195 : }
196 :
197 552 : std::string DashifyString(const std::string& underscore_string) {
198 552 : std::string result = underscore_string;
199 552 : std::replace(result.begin(), result.end(), '_', '-');
200 552 : return result;
201 : }
202 :
203 48 : void ReplaceFileContentsIfDifferent(const std::string& file_path,
204 : const std::string& contents) {
205 48 : std::ifstream old_contents_stream(file_path.c_str());
206 : std::string old_contents;
207 48 : if (old_contents_stream.good()) {
208 : std::istreambuf_iterator<char> eos;
209 0 : old_contents =
210 : std::string(std::istreambuf_iterator<char>(old_contents_stream), eos);
211 0 : old_contents_stream.close();
212 : }
213 48 : if (old_contents.length() == 0 || old_contents != contents) {
214 48 : std::ofstream new_contents_stream;
215 48 : new_contents_stream.open(file_path.c_str());
216 : new_contents_stream << contents;
217 48 : new_contents_stream.close();
218 48 : }
219 48 : }
220 :
221 : } // namespace torque
222 : } // namespace internal
223 9114 : } // namespace v8
|