import javascript

/**
 * Provides general-purpose utility predicates.
 */

 /**
  * Gets the capitalization of `s`.
  *
  * For example, the capitalization of `"function"` is `"Function"`.
  */
bindingset[s]
string capitalize(string s) {
  result = s.charAt(0).toUpperCase() + s.suffix(1)
}

/**
 * Gets the pluralization for `n` occurrences of `noun`.
 *
 * For example, the pluralization of `"function"` for `n = 2` is `"functions"`.
 */
bindingset[noun, n]
string pluralize(string noun, int n) {
  if n = 1 then
    result = noun
  else
    result = noun + "s"
}

/**
 * Gets `str` or a truncated version of `str` with `explanation` appended if its length exceeds `maxLength`.
 *
 * For example, the truncation of `"long_string"` for `maxLength = 5` and explanation `" ..."` is `"long_ ..."`.
 */
bindingset[str, maxLength, explanation]
string truncate(string str, int maxLength, string explanation) {
  if str.length() > maxLength then result = str.prefix(maxLength) + explanation else result = str
}

/**
 * Gets a string that describes `e`.
 */
string describeExpression(Expr e) {
  if e instanceof InvokeExpr then
    exists (string prefix, string suffix |
      result = prefix + suffix |
      ( if e instanceof NewExpr then
        prefix = "constructor call"
      else if e instanceof MethodCallExpr then
        prefix = "method call"
      else
        prefix = "call"
      ) and
      (
        if exists(e.(InvokeExpr).getCalleeName()) then
          suffix = " to " + e.(InvokeExpr).getCalleeName()
        else
          suffix = ""
      )
    )
  else if e instanceof Comparison then
    result = "comparison"
  else if e instanceof VarAccess then
    result = "use of variable '" + e.(VarAccess).getName() + "'"
  else if e instanceof PropAccess and exists (e.(PropAccess).getPropertyName()) then
    result = "use of property '" + e.(PropAccess).getPropertyName() + "'"
  else if e instanceof LogNotExpr then
    result = "negation"
  else
    result = "expression"
}