utils.cc 5.63 KB
Newer Older
1 2 3 4
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Marja Hölttä's avatar
Marja Hölttä committed
5
#include <algorithm>
6 7 8 9
#include <fstream>
#include <iostream>
#include <string>

10
#include "src/base/logging.h"
11
#include "src/torque/ast.h"
12 13 14 15 16 17
#include "src/torque/utils.h"

namespace v8 {
namespace internal {
namespace torque {

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
std::string StringLiteralUnquote(const std::string& s) {
  DCHECK(('"' == s.front() && '"' == s.back()) ||
         ('\'' == s.front() && '\'' == s.back()));
  std::stringstream result;
  for (size_t i = 1; i < s.length() - 1; ++i) {
    if (s[i] == '\\') {
      switch (s[++i]) {
        case 'n':
          result << '\n';
          break;
        case 'r':
          result << '\r';
          break;
        case 't':
          result << '\t';
          break;
        case '\'':
        case '"':
        case '\\':
          result << s[i];
          break;
        default:
          UNREACHABLE();
      }
    } else {
      result << s[i];
    }
  }
  return result.str();
}

std::string StringLiteralQuote(const std::string& s) {
  std::stringstream result;
  result << '"';
52
  for (size_t i = 0; i < s.length(); ++i) {
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
    switch (s[i]) {
      case '\n':
        result << "\\n";
        break;
      case '\r':
        result << "\\r";
        break;
      case '\t':
        result << "\\t";
        break;
      case '\'':
      case '"':
      case '\\':
        result << "\\" << s[i];
        break;
      default:
        result << s[i];
    }
  }
  result << '"';
  return result.str();
}

76 77 78 79
std::string CurrentPositionAsString() {
  return PositionAsString(CurrentSourcePosition::Get());
}

80 81
DEFINE_CONTEXTUAL_VARIABLE(LintErrorStatus)

82
[[noreturn]] void ReportErrorString(const std::string& error) {
83
  std::cerr << CurrentPositionAsString() << ": Torque error: " << error << "\n";
84
  v8::base::OS::Abort();
85 86
}

87
void LintError(const std::string& error) {
88
  LintErrorStatus::SetLintError();
89 90 91
  std::cerr << CurrentPositionAsString() << ": Lint error: " << error << "\n";
}

92 93 94 95 96 97 98 99
void NamingConventionError(const std::string& type, const std::string& name,
                           const std::string& convention) {
  std::stringstream sstream;
  sstream << type << " \"" << name << "\" doesn't follow \"" << convention
          << "\" naming convention.";
  LintError(sstream.str());
}

100 101 102 103 104 105 106
namespace {

bool ContainsUnderscore(const std::string& s) {
  if (s.empty()) return false;
  return s.find("_") != std::string::npos;
}

107 108 109 110 111
bool ContainsUpperCase(const std::string& s) {
  if (s.empty()) return false;
  return std::any_of(s.begin(), s.end(), [](char c) { return isupper(c); });
}

112
// Torque has some namespace constants that are used like language level
113 114 115
// keywords, e.g.: 'True', 'Undefined', etc.
// These do not need to follow the default naming convention for constants.
bool IsKeywordLikeName(const std::string& s) {
116 117
  static const char* const keyword_like_constants[]{"True", "False", "Hole",
                                                    "Null", "Undefined"};
118

119 120 121
  return std::find(std::begin(keyword_like_constants),
                   std::end(keyword_like_constants),
                   s) != std::end(keyword_like_constants);
122 123
}

124 125 126
// Untagged/MachineTypes like 'int32', 'intptr' etc. follow a 'all-lowercase'
// naming convention and are those exempt from the normal type convention.
bool IsMachineType(const std::string& s) {
127
  static const char* const machine_types[]{
128 129 130
      "void",    "never",   "int32",   "uint32", "int64",  "intptr",
      "uintptr", "float32", "float64", "bool",   "string", "int31"};

131 132
  return std::find(std::begin(machine_types), std::end(machine_types), s) !=
         std::end(machine_types);
133 134
}

135 136 137 138 139 140 141 142 143 144 145 146
}  // namespace

bool IsLowerCamelCase(const std::string& s) {
  if (s.empty()) return false;
  return islower(s[0]) && !ContainsUnderscore(s);
}

bool IsUpperCamelCase(const std::string& s) {
  if (s.empty()) return false;
  return isupper(s[0]) && !ContainsUnderscore(s);
}

147 148 149 150 151
bool IsSnakeCase(const std::string& s) {
  if (s.empty()) return false;
  return !ContainsUpperCase(s);
}

152
bool IsValidNamespaceConstName(const std::string& s) {
153 154 155 156 157 158
  if (s.empty()) return false;
  if (IsKeywordLikeName(s)) return true;

  return s[0] == 'k' && IsUpperCamelCase(s.substr(1));
}

159 160 161 162 163 164 165
bool IsValidTypeName(const std::string& s) {
  if (s.empty()) return false;
  if (IsMachineType(s)) return true;

  return IsUpperCamelCase(s);
}

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
std::string CamelifyString(const std::string& underscore_string) {
  std::string result;
  bool word_beginning = true;
  for (auto current : underscore_string) {
    if (current == '_' || current == '-') {
      word_beginning = true;
      continue;
    }
    if (word_beginning) {
      current = toupper(current);
    }
    result += current;
    word_beginning = false;
  }
  return result;
}

183 184 185 186 187 188
std::string DashifyString(const std::string& underscore_string) {
  std::string result = underscore_string;
  std::replace(result.begin(), result.end(), '_', '-');
  return result;
}

189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
void ReplaceFileContentsIfDifferent(const std::string& file_path,
                                    const std::string& contents) {
  std::ifstream old_contents_stream(file_path.c_str());
  std::string old_contents;
  if (old_contents_stream.good()) {
    std::istreambuf_iterator<char> eos;
    old_contents =
        std::string(std::istreambuf_iterator<char>(old_contents_stream), eos);
    old_contents_stream.close();
  }
  if (old_contents.length() == 0 || old_contents != contents) {
    std::ofstream new_contents_stream;
    new_contents_stream.open(file_path.c_str());
    new_contents_stream << contents;
    new_contents_stream.close();
  }
}

}  // namespace torque
}  // namespace internal
}  // namespace v8