# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Presubmit script for ios.

See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into depot_tools.
"""

import os

USE_PYTHON3 = True

NULLABILITY_PATTERN = r'(nonnull|nullable|_Nullable|_Nonnull)'
TODO_PATTERN = r'TO[D]O\(([^\)]*)\)'
CRBUG_PATTERN = r'crbug\.com/\d+$'
ARC_COMPILE_GUARD = [
    '#if !defined(__has_feature) || !__has_feature(objc_arc)',
    '#error "This file requires ARC support."',
    '#endif',
]

def IsSubListOf(needle, hay):
  """Returns whether there is a slice of |hay| equal to |needle|."""
  for i, line in enumerate(hay):
    if line == needle[0]:
      if needle == hay[i:i+len(needle)]:
        return True
  return False

def _CheckARCCompilationGuard(input_api, output_api):
  """ Checks whether new objc files have proper ARC compile guards."""
  files_without_headers = []
  for f in input_api.AffectedFiles():
    if f.Action() != 'A':
      continue

    _, ext = os.path.splitext(f.LocalPath())
    if ext not in ('.m', '.mm'):
      continue

    if not IsSubListOf(ARC_COMPILE_GUARD, f.NewContents()):
      files_without_headers.append(f.LocalPath())

  if not files_without_headers:
    return []

  plural_suffix = '' if len(files_without_headers) == 1 else 's'
  error_message = '\n'.join([
      'Found new Objective-C implementation file%(plural)s without compile'
      ' guard%(plural)s. Please use the following compile guard'
      ':' % {'plural': plural_suffix}
  ] + ARC_COMPILE_GUARD + files_without_headers) + '\n'

  return [output_api.PresubmitError(error_message)]


def _CheckNullabilityAnnotations(input_api, output_api):
  """ Checks whether there are nullability annotations in ios code."""
  nullability_regex = input_api.re.compile(NULLABILITY_PATTERN)

  errors = []
  for f in input_api.AffectedFiles():
    for line_num, line in f.ChangedContents():
      if nullability_regex.search(line):
        errors.append('%s:%s' % (f.LocalPath(), line_num))
  if not errors:
    return []

  plural_suffix = '' if len(errors) == 1 else 's'
  error_message = ('Found Nullability annotation%(plural)s. '
      'Prefer DCHECKs in ios code to check for nullness:'
       % {'plural': plural_suffix})

  return [output_api.PresubmitPromptWarning(error_message, items=errors)]


def _CheckBugInToDo(input_api, output_api):
  """ Checks whether TODOs in ios code are identified by a bug number."""
  errors = []
  for f in input_api.AffectedFiles():
    for line_num, line in f.ChangedContents():
      if _HasToDoWithNoBug(input_api, line):
        errors.append('%s:%s' % (f.LocalPath(), line_num))
  if not errors:
    return []

  plural_suffix = '' if len(errors) == 1 else 's'
  error_message = '\n'.join([
      'Found TO''DO%(plural)s without bug number%(plural)s (expected format is '
      '\"TO''DO(crbug.com/######)\":' % {'plural': plural_suffix}
  ] + errors) + '\n'

  return [output_api.PresubmitError(error_message)]


def _HasToDoWithNoBug(input_api, line):
  """ Returns True if TODO is not identified by a bug number."""
  todo_regex = input_api.re.compile(TODO_PATTERN)
  crbug_regex = input_api.re.compile(CRBUG_PATTERN)

  todo_match = todo_regex.search(line)
  if not todo_match:
    return False
  crbug_match = crbug_regex.match(todo_match.group(1))
  return not crbug_match


def CheckChangeOnUpload(input_api, output_api):
  results = []
  results.extend(_CheckBugInToDo(input_api, output_api))
  results.extend(_CheckNullabilityAnnotations(input_api, output_api))
  results.extend(_CheckARCCompilationGuard(input_api, output_api))
  return results
