#!/usr/bin/env python3
#
# Copyright (c) 2020 Valve Corporation
# Copyright (c) 2020 LunarG, Inc.
#
# 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.
#
# Author: Mike Schuchardt <mikes@lunarg.com>

# Scrub source code of "aliases" -- extension types and enums that have been promoted to core.
#
# Usage: antialias_source.py XML_PATH SOURCE_PATH...
# 
# Notes:
# - Source code generators need to be re-run after this script due to
#   inconsitencies in the registry with regard to alias usage
# - Clang-format needs to be re-run after this script

import sys
import os
import re
from xml.etree import ElementTree

SOURCE_EXTS = ['.h', '.c', '.cpp', '.inc', '.py']

def GetAliases(xml_path):
    tree = ElementTree.parse(xml_path)
    root = tree.getroot()

    suffixes = [tag.get('name') for tag in root.findall('tags/tag')]

    aliases = {}
    alias_elements = []
    alias_elements.extend(root.findall('types/type[@alias]'))
    alias_elements.extend(root.findall('enums/enum[@alias]'))
    # extension types are covered above in types/type
    alias_elements.extend(root.findall('extensions/extension/require/enum[@alias]'))
    # DON'T try to do commands, those aliases are not binary compatible and we still need to handle both
    for alias_element in alias_elements:
        alias = alias_element.get('alias')
        name = alias_element.get('name')
        # Look for un-suffixed alias (core)
        if not any(alias.endswith(s) for s in suffixes):
            aliases[name] = alias
    return aliases

def UpdateFile(alias_map, filename):
    with open(filename) as f:
        file_contents = f.read()
    sub_count = 0
    for name, alias in alias_map.items():
        if name in file_contents:
            # Use regex with word break to match whole tokens only
            file_contents, n = re.subn(r'\b{}\b'.format(name), alias, file_contents)
            sub_count += n
    if sub_count > 0:
        print('{} {}'.format(filename, sub_count))
        with open(filename, 'w') as f:
            f.write(file_contents)

def UpdateDir(alias_map, path):
    for dirpath, dirnames, filenames in os.walk(path):
        for filename in filenames:
            if any(filename.endswith(ext) for ext in SOURCE_EXTS):
                UpdateFile(alias_map, os.path.join(dirpath, filename))

def Main():
    if len(sys.argv) < 3 or not sys.argv[1].endswith('.xml'):
        print('Usage: antialias_source.py XML_PATH SOURCE_PATH...')
        sys.exit(1)
    xml_path = sys.argv[1]
    source_paths = sys.argv[2:]

    aliases = GetAliases(xml_path)
    for source_path in source_paths:
        if os.path.isfile(source_path):
            UpdateFile(aliases, source_path)
        elif os.path.isdir(source_path):
            UpdateDir(aliases, source_path)

if __name__ == '__main__':
    Main()


