# This Python script can be used to add override statements where they are
# reported to be needed according to warnings produced by clang-700.1.76 on macOS
# 10.11.6 with the -Winconsistent-missing-override option enabled. To run the
# script, invoke

# > python AddOverrides.py <overrides.txt>

# Each line of the overrides.txt file has the form

# <source file>:<line number>:<position>: warning: 'RequestDataDescription' \
#   overrides a member function but is not marked 'override' [-Winconsistent-missing-override]

# It can be generated by running

# > ninja clean
# > ninja &> output.txt
# > grep "overrides a member function but" output.txt | sort | uniq > overrides.txt

# The script should be idempotent, so it can be run a second time without adversly
# affecting files that have already been modified during a first run.

import re
import sys
import __future__

lines_map = {}

# Load override warning file. Store file name as key and list of lines to modify
# as values.
with open(sys.argv[1], 'r') as f:
  for line in f:
    components = line.split(':')
    file_name = components[0]
    line_number = int(components[1])
    if file_name in lines_map:
      lines_map[file_name].add(line_number)
    else:
      lines_map[file_name] = {line_number}
    #break

# Sort the line numbers
for k, v in lines_map.items():
  sorted_line_numbers = sorted(v)
  lines_map[k] = sorted_line_numbers

# Now open each file in the dictionary, append override to the end of each
# line, and save out the modified file

for file_name, line_numbers in lines_map.items():
  lines = []
  with open(file_name, 'r') as f:
    contents = f.read()
    lines = contents.split('\n')
    f.close()

  out_file = open(file_name, 'w')

  counter = 1
  in_multi_line = False
  for line in lines:

    if line.find('override') >= 0:
      in_multi_line = False
    else:

      if in_multi_line or (counter in line_numbers and re.match('^vtk.*Macro', line.lstrip()) is None):
        if line.endswith(');'):
          line = line[0:-1] + ' override;'
          in_multi_line = False
          #print(65, file_name, line, counter)
        elif line.endswith('=0;'):
          line = line[0:-3] + ' override = 0;'
          in_multi_line = False
        elif line.endswith(' = 0;'):
          line = line[0:-5] + ' override = 0;'
          in_multi_line = False
        elif line.endswith(')'):
          line = line + ' override'
          in_multi_line = False
          #print(75, file_name, line, counter)
        elif line.find('{') >= 0:
          idx = line.find('{')
          line = line[:idx].rstrip() + ' override ' + line[idx:].lstrip()
          in_multi_line = False
          print(65, file_name, line, counter)
        elif line.endswith(',') or line.endswith('('):
          in_multi_line = True

    counter = counter + 1
    out_file.write('%s' % line)
    if counter <= len(lines):
      out_file.write('\n')

  out_file.close()
