# -*- coding: utf-8 -*-
# Copyright 2015 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for yapf.style."""

import os
import shutil
import tempfile
import textwrap
import unittest

from yapf.yapflib import style

from yapftests import utils
from yapftests import yapf_test_helper


class UtilsTest(yapf_test_helper.YAPFTest):

  def testContinuationAlignStyleStringConverter(self):
    for cont_align_space in ('', 'space', '"space"', '\'space\''):
      self.assertEqual(
          style._ContinuationAlignStyleStringConverter(cont_align_space),
          'SPACE')
    for cont_align_fixed in ('fixed', '"fixed"', '\'fixed\''):
      self.assertEqual(
          style._ContinuationAlignStyleStringConverter(cont_align_fixed),
          'FIXED')
    for cont_align_valignright in (
        'valign-right',
        '"valign-right"',
        '\'valign-right\'',
        'valign_right',
        '"valign_right"',
        '\'valign_right\'',
    ):
      self.assertEqual(
          style._ContinuationAlignStyleStringConverter(cont_align_valignright),
          'VALIGN-RIGHT')
    with self.assertRaises(ValueError) as ctx:
      style._ContinuationAlignStyleStringConverter('blahblah')
    self.assertIn("unknown continuation align style: 'blahblah'",
                  str(ctx.exception))

  def testStringListConverter(self):
    self.assertEqual(style._StringListConverter('foo, bar'), ['foo', 'bar'])
    self.assertEqual(style._StringListConverter('foo,bar'), ['foo', 'bar'])
    self.assertEqual(style._StringListConverter('  foo'), ['foo'])
    self.assertEqual(
        style._StringListConverter('joe  ,foo,  bar'), ['joe', 'foo', 'bar'])

  def testBoolConverter(self):
    self.assertEqual(style._BoolConverter('true'), True)
    self.assertEqual(style._BoolConverter('1'), True)
    self.assertEqual(style._BoolConverter('false'), False)
    self.assertEqual(style._BoolConverter('0'), False)

  def testIntListConverter(self):
    self.assertEqual(style._IntListConverter('1, 2, 3'), [1, 2, 3])
    self.assertEqual(style._IntListConverter('[ 1, 2, 3 ]'), [1, 2, 3])
    self.assertEqual(style._IntListConverter('[ 1, 2, 3, ]'), [1, 2, 3])

  def testIntOrIntListConverter(self):
    self.assertEqual(style._IntOrIntListConverter('10'), 10)
    self.assertEqual(style._IntOrIntListConverter('1, 2, 3'), [1, 2, 3])


def _LooksLikeGoogleStyle(cfg):
  return cfg['COLUMN_LIMIT'] == 80 and cfg['SPLIT_COMPLEX_COMPREHENSION']


def _LooksLikePEP8Style(cfg):
  return cfg['COLUMN_LIMIT'] == 79


def _LooksLikeFacebookStyle(cfg):
  return cfg['DEDENT_CLOSING_BRACKETS']


def _LooksLikeYapfStyle(cfg):
  return cfg['SPLIT_BEFORE_DOT']


class PredefinedStylesByNameTest(yapf_test_helper.YAPFTest):

  @classmethod
  def setUpClass(cls):  # pylint: disable=g-missing-super-call
    style.SetGlobalStyle(style.CreatePEP8Style())

  def testDefault(self):
    # default is PEP8
    cfg = style.CreateStyleFromConfig(None)
    self.assertTrue(_LooksLikePEP8Style(cfg))

  def testPEP8ByName(self):
    for pep8_name in ('PEP8', 'pep8', 'Pep8'):
      cfg = style.CreateStyleFromConfig(pep8_name)
      self.assertTrue(_LooksLikePEP8Style(cfg))

  def testGoogleByName(self):
    for google_name in ('google', 'Google', 'GOOGLE'):
      cfg = style.CreateStyleFromConfig(google_name)
      self.assertTrue(_LooksLikeGoogleStyle(cfg))

  def testYapfByName(self):
    for yapf_name in ('yapf', 'YAPF'):
      cfg = style.CreateStyleFromConfig(yapf_name)
      self.assertTrue(_LooksLikeYapfStyle(cfg))

  def testFacebookByName(self):
    for fb_name in ('facebook', 'FACEBOOK', 'Facebook'):
      cfg = style.CreateStyleFromConfig(fb_name)
      self.assertTrue(_LooksLikeFacebookStyle(cfg))


class StyleFromFileTest(yapf_test_helper.YAPFTest):

  @classmethod
  def setUpClass(cls):  # pylint: disable=g-missing-super-call
    cls.test_tmpdir = tempfile.mkdtemp()
    style.SetGlobalStyle(style.CreatePEP8Style())

  @classmethod
  def tearDownClass(cls):  # pylint: disable=g-missing-super-call
    shutil.rmtree(cls.test_tmpdir)

  def testDefaultBasedOnStyle(self):
    cfg = textwrap.dedent('''\
        [style]
        continuation_indent_width = 20
        ''')
    with utils.TempFileContents(self.test_tmpdir, cfg) as filepath:
      cfg = style.CreateStyleFromConfig(filepath)
      self.assertTrue(_LooksLikePEP8Style(cfg))
      self.assertEqual(cfg['CONTINUATION_INDENT_WIDTH'], 20)

  def testDefaultBasedOnPEP8Style(self):
    cfg = textwrap.dedent('''\
        [style]
        based_on_style = pep8
        continuation_indent_width = 40
        ''')
    with utils.TempFileContents(self.test_tmpdir, cfg) as filepath:
      cfg = style.CreateStyleFromConfig(filepath)
      self.assertTrue(_LooksLikePEP8Style(cfg))
      self.assertEqual(cfg['CONTINUATION_INDENT_WIDTH'], 40)

  def testDefaultBasedOnGoogleStyle(self):
    cfg = textwrap.dedent('''\
        [style]
        based_on_style = google
        continuation_indent_width = 20
        ''')
    with utils.TempFileContents(self.test_tmpdir, cfg) as filepath:
      cfg = style.CreateStyleFromConfig(filepath)
      self.assertTrue(_LooksLikeGoogleStyle(cfg))
      self.assertEqual(cfg['CONTINUATION_INDENT_WIDTH'], 20)

  def testDefaultBasedOnFacebookStyle(self):
    cfg = textwrap.dedent('''\
        [style]
        based_on_style = facebook
        continuation_indent_width = 20
        ''')
    with utils.TempFileContents(self.test_tmpdir, cfg) as filepath:
      cfg = style.CreateStyleFromConfig(filepath)
      self.assertTrue(_LooksLikeFacebookStyle(cfg))
      self.assertEqual(cfg['CONTINUATION_INDENT_WIDTH'], 20)

  def testBoolOptionValue(self):
    cfg = textwrap.dedent('''\
        [style]
        based_on_style = pep8
        SPLIT_BEFORE_NAMED_ASSIGNS=False
        split_before_logical_operator = true
        ''')
    with utils.TempFileContents(self.test_tmpdir, cfg) as filepath:
      cfg = style.CreateStyleFromConfig(filepath)
      self.assertTrue(_LooksLikePEP8Style(cfg))
      self.assertEqual(cfg['SPLIT_BEFORE_NAMED_ASSIGNS'], False)
      self.assertEqual(cfg['SPLIT_BEFORE_LOGICAL_OPERATOR'], True)

  def testStringListOptionValue(self):
    cfg = textwrap.dedent('''\
        [style]
        based_on_style = pep8
        I18N_FUNCTION_CALL = N_, V_, T_
        ''')
    with utils.TempFileContents(self.test_tmpdir, cfg) as filepath:
      cfg = style.CreateStyleFromConfig(filepath)
      self.assertTrue(_LooksLikePEP8Style(cfg))
      self.assertEqual(cfg['I18N_FUNCTION_CALL'], ['N_', 'V_', 'T_'])

  def testErrorNoStyleFile(self):
    with self.assertRaisesRegex(style.StyleConfigError,
                                'is not a valid style or file path'):
      style.CreateStyleFromConfig('/8822/xyznosuchfile')

  def testErrorNoStyleSection(self):
    cfg = textwrap.dedent('''\
        [s]
        indent_width=2
        ''')
    with utils.TempFileContents(self.test_tmpdir, cfg) as filepath:
      with self.assertRaisesRegex(style.StyleConfigError,
                                  'Unable to find section'):
        style.CreateStyleFromConfig(filepath)

  def testErrorUnknownStyleOption(self):
    cfg = textwrap.dedent('''\
        [style]
        indent_width=2
        hummus=2
        ''')
    with utils.TempFileContents(self.test_tmpdir, cfg) as filepath:
      with self.assertRaisesRegex(style.StyleConfigError,
                                  'Unknown style option'):
        style.CreateStyleFromConfig(filepath)

  def testPyprojectTomlNoYapfSection(self):
    try:
      import tomli  # noqa: F401
    except ImportError:
      return

    filepath = os.path.join(self.test_tmpdir, 'pyproject.toml')
    _ = open(filepath, 'w')
    with self.assertRaisesRegex(style.StyleConfigError,
                                'Unable to find section'):
      style.CreateStyleFromConfig(filepath)

  def testPyprojectTomlParseYapfSection(self):
    try:
      import tomli  # noqa: F401
    except ImportError:
      return

    cfg = textwrap.dedent('''\
        [tool.yapf]
        based_on_style = "pep8"
        continuation_indent_width = 40
        ''')
    filepath = os.path.join(self.test_tmpdir, 'pyproject.toml')
    with open(filepath, 'w') as f:
      f.write(cfg)
    cfg = style.CreateStyleFromConfig(filepath)
    self.assertTrue(_LooksLikePEP8Style(cfg))
    self.assertEqual(cfg['CONTINUATION_INDENT_WIDTH'], 40)


class StyleFromDict(yapf_test_helper.YAPFTest):

  @classmethod
  def setUpClass(cls):  # pylint: disable=g-missing-super-call
    style.SetGlobalStyle(style.CreatePEP8Style())

  def testDefaultBasedOnStyle(self):
    config_dict = {
        'based_on_style': 'pep8',
        'indent_width': 2,
        'blank_line_before_nested_class_or_def': True
    }
    cfg = style.CreateStyleFromConfig(config_dict)
    self.assertTrue(_LooksLikePEP8Style(cfg))
    self.assertEqual(cfg['INDENT_WIDTH'], 2)

  def testDefaultBasedOnStyleBadDict(self):
    self.assertRaisesRegex(style.StyleConfigError, 'Unknown style option',
                           style.CreateStyleFromConfig,
                           {'based_on_styl': 'pep8'})
    self.assertRaisesRegex(style.StyleConfigError, 'not a valid',
                           style.CreateStyleFromConfig,
                           {'INDENT_WIDTH': 'FOUR'})


class StyleFromCommandLine(yapf_test_helper.YAPFTest):

  @classmethod
  def setUpClass(cls):  # pylint: disable=g-missing-super-call
    style.SetGlobalStyle(style.CreatePEP8Style())

  def testDefaultBasedOnStyle(self):
    cfg = style.CreateStyleFromConfig(
        '{based_on_style: pep8,'
        ' indent_width: 2,'
        ' blank_line_before_nested_class_or_def: True}')
    self.assertTrue(_LooksLikePEP8Style(cfg))
    self.assertEqual(cfg['INDENT_WIDTH'], 2)

  def testDefaultBasedOnStyleNotStrict(self):
    cfg = style.CreateStyleFromConfig(
        '{based_on_style : pep8'
        ' ,indent_width=2'
        ' blank_line_before_nested_class_or_def:True}')
    self.assertTrue(_LooksLikePEP8Style(cfg))
    self.assertEqual(cfg['INDENT_WIDTH'], 2)

  def testDefaultBasedOnExplicitlyUnicodeTypeString(self):
    cfg = style.CreateStyleFromConfig('{}')
    self.assertIsInstance(cfg, dict)

  def testDefaultBasedOnDetaultTypeString(self):
    cfg = style.CreateStyleFromConfig('{}')
    self.assertIsInstance(cfg, dict)

  def testDefaultBasedOnStyleBadString(self):
    self.assertRaisesRegex(style.StyleConfigError, 'Unknown style option',
                           style.CreateStyleFromConfig, '{based_on_styl: pep8}')
    self.assertRaisesRegex(style.StyleConfigError, 'not a valid',
                           style.CreateStyleFromConfig, '{INDENT_WIDTH: FOUR}')
    self.assertRaisesRegex(style.StyleConfigError, 'Invalid style dict',
                           style.CreateStyleFromConfig, '{based_on_style: pep8')


class StyleHelp(yapf_test_helper.YAPFTest):

  def testHelpKeys(self):
    settings = sorted(style.Help())
    expected = sorted(style._style)
    self.assertListEqual(settings, expected)


if __name__ == '__main__':
  unittest.main()
