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 299 : std::string StringLiteralUnquote(const std::string& s) {
19 : DCHECK(('"' == s.front() && '"' == s.back()) ||
20 : ('\'' == s.front() && '\'' == s.back()));
21 299 : std::stringstream result;
22 8456 : for (size_t i = 1; i < s.length() - 1; ++i) {
23 3929 : 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 299 : return result.str();
47 : }
48 :
49 342 : std::string StringLiteralQuote(const std::string& s) {
50 342 : std::stringstream result;
51 : result << '"';
52 25958 : for (size_t i = 0; i < s.length(); ++i) {
53 12637 : 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 214 : result << "\\" << s[i];
67 : break;
68 : default:
69 : result << s[i];
70 : }
71 : }
72 : result << '"';
73 342 : 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 2612 : bool ContainsUnderscore(const std::string& s) {
103 2612 : if (s.empty()) return false;
104 2612 : return s.find("_") != std::string::npos;
105 : }
106 :
107 21 : bool ContainsUpperCase(const std::string& s) {
108 21 : if (s.empty()) return false;
109 136 : 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", "int32", "uint32", "int64", "intptr", "uintptr",
129 : "float32", "float64", "bool", "string", "bint", "int31"};
130 :
131 : return std::find(std::begin(machine_types), std::end(machine_types), s) !=
132 : std::end(machine_types);
133 : }
134 :
135 : } // namespace
136 :
137 1903 : bool IsLowerCamelCase(const std::string& s) {
138 1903 : if (s.empty()) return false;
139 1903 : return islower(s[0]) && !ContainsUnderscore(s);
140 : }
141 :
142 709 : bool IsUpperCamelCase(const std::string& s) {
143 709 : if (s.empty()) return false;
144 709 : return isupper(s[0]) && !ContainsUnderscore(s);
145 : }
146 :
147 21 : bool IsSnakeCase(const std::string& s) {
148 21 : if (s.empty()) return false;
149 21 : return !ContainsUpperCase(s);
150 : }
151 :
152 40 : bool IsValidNamespaceConstName(const std::string& s) {
153 40 : if (s.empty()) return false;
154 40 : if (IsKeywordLikeName(s)) return true;
155 :
156 70 : return s[0] == 'k' && IsUpperCamelCase(s.substr(1));
157 : }
158 :
159 91 : bool IsValidTypeName(const std::string& s) {
160 91 : if (s.empty()) return false;
161 91 : if (IsMachineType(s)) return true;
162 :
163 78 : return IsUpperCamelCase(s);
164 : }
165 :
166 7 : std::string CapifyStringWithUnderscores(const std::string& camellified_string) {
167 : std::string result;
168 : bool previousWasLower = false;
169 101 : for (auto current : camellified_string) {
170 87 : if (previousWasLower && isupper(current)) {
171 : result += "_";
172 : }
173 87 : result += toupper(current);
174 87 : previousWasLower = (islower(current));
175 : }
176 7 : return result;
177 : }
178 :
179 1827 : std::string CamelifyString(const std::string& underscore_string) {
180 : std::string result;
181 : bool word_beginning = true;
182 13391 : for (auto current : underscore_string) {
183 9737 : if (current == '_' || current == '-') {
184 : word_beginning = true;
185 : continue;
186 : }
187 9621 : if (word_beginning) {
188 1943 : current = toupper(current);
189 : }
190 : result += current;
191 : word_beginning = false;
192 : }
193 1827 : return result;
194 : }
195 :
196 110 : std::string DashifyString(const std::string& underscore_string) {
197 110 : std::string result = underscore_string;
198 110 : std::replace(result.begin(), result.end(), '_', '-');
199 110 : return result;
200 : }
201 :
202 22 : void ReplaceFileContentsIfDifferent(const std::string& file_path,
203 : const std::string& contents) {
204 22 : std::ifstream old_contents_stream(file_path.c_str());
205 : std::string old_contents;
206 22 : if (old_contents_stream.good()) {
207 : std::istreambuf_iterator<char> eos;
208 0 : old_contents =
209 : std::string(std::istreambuf_iterator<char>(old_contents_stream), eos);
210 0 : old_contents_stream.close();
211 : }
212 22 : if (old_contents.length() == 0 || old_contents != contents) {
213 22 : std::ofstream new_contents_stream;
214 22 : new_contents_stream.open(file_path.c_str());
215 : new_contents_stream << contents;
216 22 : new_contents_stream.close();
217 22 : }
218 22 : }
219 :
220 : } // namespace torque
221 : } // namespace internal
222 9078 : } // namespace v8
|