module SyntaxTree::Quotes

def self.locked?(node, quote)

quotes, then single quotes would deactivate it.)
quoting would activate the escape sequence, and if they chose double
whichever quote the user chose. (If they chose single quotes, then double
that contains the interpolation pattern ("#{"), then we are locked into
If there is some part of this string that matches an escape sequence or
def self.locked?(node, quote)
  node.parts.any? do |part|
    !part.is_a?(TStringContent) || part.value.match?(/\\|#[@${]|#{quote}/)
  end
end

def self.matching(quote)

Find the matching closing quote for the given opening quote.
def self.matching(quote)
  PAIRS.fetch(quote) { quote }
end

def self.normalize(content, enclosing)

enclose +content+ with +enclosing+.
Escape and unescape single and double quotes as needed to be able to
def self.normalize(content, enclosing)
  return content if enclosing != "\"" && enclosing != "'"
  content.gsub(/\\([\s\S])|(['"])/) do
    _match, escaped, quote = Regexp.last_match.to_a
    if quote == enclosing
      "\\#{quote}"
    elsif quote
      quote
    else
      "\\#{escaped}"
    end
  end
end