# SPDX-License-Identifier: Apache-2.0
# Copyright 2014-2016 The Meson development team

from __future__ import annotations

"""This is a helper script for IDE developers. It allows you to
extract information such as list of targets, files, compiler flags,
tests and so on. All output is in JSON for simple parsing.

Currently only works for the Ninja backend. Others use generated
project files and don't need this info."""

from contextlib import redirect_stdout
import dataclasses
import itertools
import json
import os
from pathlib import Path, PurePath
import sys
import typing as T

from . import build, environment, mesonlib, options, coredata as cdata
from .ast import IntrospectionInterpreter, AstConditionLevel, AstIDGenerator, AstIndentationGenerator, AstJSONPrinter
from .backend import backends
from .interpreterbase import UnknownValue
from .options import OptionKey

if T.TYPE_CHECKING:
    import argparse

    from .dependencies import Dependency

class IntrospectionEncoder(json.JSONEncoder):
    def default(self, obj: T.Any) -> T.Any:
        if isinstance(obj, UnknownValue):
            return 'unknown'
        return json.JSONEncoder.default(self, obj)

def get_meson_info_file(info_dir: str) -> str:
    return os.path.join(info_dir, 'meson-info.json')

def get_meson_introspection_version() -> str:
    return '1.0.0'

def get_meson_introspection_required_version() -> T.List[str]:
    return ['>=1.0', '<2.0']

def dump_ast(intr: IntrospectionInterpreter) -> T.Dict[str, T.Any]:
    printer = AstJSONPrinter()
    intr.ast.accept(printer)
    return printer.result

def list_installed(coredata: cdata.CoreData, builddata: build.Build, backend: backends.Backend) -> T.Dict[str, str]:
    res = {}
    installdata = backend.create_install_data()
    for t in installdata.targets:
        res[os.path.join(installdata.build_dir, t.fname)] = \
            os.path.join(installdata.prefix, t.outdir, os.path.basename(t.fname))
    for i in installdata.data:
        res[i.path] = os.path.join(installdata.prefix, i.install_path)
    for i in installdata.headers:
        res[i.path] = os.path.join(installdata.prefix, i.install_path, os.path.basename(i.path))
    for i in installdata.man:
        res[i.path] = os.path.join(installdata.prefix, i.install_path)
    for i in installdata.install_subdirs:
        res[i.path] = os.path.join(installdata.prefix, i.install_path)
    for s in installdata.symlinks:
        basename = os.path.basename(s.name)
        res[basename] = os.path.join(installdata.prefix, s.install_path, basename)
    return res

def list_install_plan(coredata: cdata.CoreData, builddata: build.Build, backend: backends.Backend) -> T.Dict[str, T.Dict[str, T.Dict[str, T.Union[str, T.List[str], None]]]]:
    installdata = backend.create_install_data()
    plan: T.Dict[str, T.Dict[str, T.Dict[str, T.Union[str, T.List[str], None]]]] = {
        'targets': {
            os.path.join(installdata.build_dir, target.fname): {
                'destination': target.out_name,
                'tag': target.tag or None,
                'subproject': target.subproject or None,
                'install_rpath': target.install_rpath or None,
                'build_rpaths': sorted(x.decode('utf8') for x in target.rpath_dirs_to_remove),
            }
            for target in installdata.targets
        },
    }
    for key, data_list in {
        'data': installdata.data,
        'man': installdata.man,
        'headers': installdata.headers,
        'install_subdirs': installdata.install_subdirs
    }.items():
        # Mypy doesn't recognize SubdirInstallData as a subclass of InstallDataBase
        for data in data_list: # type: ignore[attr-defined]
            data_type = data.data_type or key
            install_path_name = data.install_path_name
            if key == 'headers':  # in the headers, install_path_name is the directory
                install_path_name = os.path.join(install_path_name, os.path.basename(data.path))

            entry = {
                'destination': install_path_name,
                'tag': data.tag or None,
                'subproject': data.subproject or None,
            }

            if key == 'install_subdirs':
                exclude_files, exclude_dirs = data.exclude or ([], [])
                entry['exclude_dirs'] = list(exclude_dirs)
                entry['exclude_files'] = list(exclude_files)

            plan[data_type] = plan.get(data_type, {})
            plan[data_type][data.path] = entry

    return plan

def get_target_dir(coredata: cdata.CoreData, subdir: str) -> str:
    if coredata.optstore.get_value_for(OptionKey('layout')) == 'flat':
        return 'meson-out'
    else:
        return subdir

def list_targets_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, object]]:
    tlist: T.List[T.Dict[str, object]] = []
    root_dir = Path(intr.source_root).resolve()

    for i in intr.targets:
        sources = intr.nodes_to_pretty_filelist(root_dir, i.subdir, i.source_nodes)
        extra_files = intr.nodes_to_pretty_filelist(root_dir, i.subdir, [i.extra_files] if i.extra_files else [])

        outdir = get_target_dir(intr.coredata, i.subdir)

        tlist += [{
            'name': i.name,
            'id': i.id,
            'type': i.typename,
            'defined_in': i.defined_in,
            'filename': [os.path.join(outdir, x) for x in i.outputs],
            'build_by_default': i.build_by_default,
            'target_sources': [{
                'language': 'unknown',
                'machine': i.machine,
                'compiler': [],
                'parameters': [],
                'sources': sources,
                'generated_sources': []
            }],
            'depends': [],
            'extra_files': extra_files,
            'subproject': None, # Subprojects are not supported
            'installed': i.installed
        }]

    return tlist

def list_targets(coredata: cdata.CoreData, builddata: build.Build, backend: backends.Backend) -> T.List[T.Any]:
    tlist: T.List[T.Any] = []
    build_dir = builddata.environment.get_build_dir()
    src_dir = builddata.environment.get_source_dir()

    # Fast lookup table for installation files
    install_lookuptable = {}
    installdata = backend.create_install_data()
    for i in installdata.targets:
        basename = os.path.basename(i.fname)
        install_lookuptable[basename] = [str(PurePath(installdata.prefix, i.outdir, basename))]
    for s in installdata.symlinks:
        # Symlink's target must already be in the table. They share the same list
        # to support symlinks to symlinks recursively, such as .so -> .so.0 -> .so.1.2.3
        basename = os.path.basename(s.name)
        try:
            install_lookuptable[basename] = install_lookuptable[os.path.basename(s.target)]
            install_lookuptable[basename].append(str(PurePath(installdata.prefix, s.install_path, basename)))
        except KeyError:
            pass

    for (idname, target) in builddata.get_targets().items():
        if not isinstance(target, build.Target):
            raise RuntimeError('The target object in `builddata.get_targets()` is not of type `build.Target`. Please file a bug with this error message.')

        outdir = get_target_dir(builddata.environment.coredata, target.get_builddir())
        t = {
            'name': target.get_basename(),
            'id': idname,
            'type': target.get_typename(),
            'defined_in': os.path.normpath(os.path.join(src_dir, target.get_subdir(), environment.build_filename)),
            'filename': [os.path.join(build_dir, outdir, x) for x in target.get_outputs()],
            'build_by_default': target.build_by_default,
            'target_sources': backend.get_introspection_data(idname, target),
            'extra_files': [os.path.normpath(os.path.join(src_dir, x.subdir, x.fname)) for x in target.extra_files],
            'subproject': target.subproject or None,
            'dependencies': [d.name for d in getattr(target, 'external_deps', [])],
            'depends': [lib.get_id() for lib in getattr(target, 'dependencies', [])]
        }

        vs_module_defs = getattr(target, 'vs_module_defs', None)
        if vs_module_defs is not None:
            t['vs_module_defs'] = vs_module_defs.relative_name()
        win_subsystem = getattr(target, 'win_subsystem', None)
        if win_subsystem is not None:
            t['win_subsystem'] = win_subsystem

        if target.should_install():
            t['installed'] = True
            ifn = [install_lookuptable.get(x, [None]) for x in target.get_outputs()]
            t['install_filename'] = [x for sublist in ifn for x in sublist]  # flatten the list
        else:
            t['installed'] = False
        tlist.append(t)
    return tlist

def list_buildoptions(coredata: cdata.CoreData, builddata: build.Build, backend: backends.Backend) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]:
    return _list_buildoptions(coredata)

def list_buildoptions_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]:
    subprojects = [i['name'] for i in intr.project_data['subprojects']]
    return _list_buildoptions(intr.coredata, subprojects)

def _list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[str]] = None) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]:
    optlist: T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]] = []
    subprojects = subprojects or []

    dir_option_names = set(options.BUILTIN_DIR_OPTIONS)
    test_option_names = {OptionKey('errorlogs'),
                         OptionKey('stdsplit')}

    dir_options: options.MutableKeyedOptionDictType = {}
    test_options: options.MutableKeyedOptionDictType = {}
    core_options: options.MutableKeyedOptionDictType = {}
    for k, v in coredata.optstore.items():
        if k in dir_option_names:
            dir_options[k] = v
        elif k in test_option_names:
            test_options[k] = v
        elif coredata.optstore.is_builtin_option(k):
            core_options[k] = v
            if not v.yielding:
                for s in subprojects:
                    core_options[k.evolve(subproject=s)] = v

    def add_keys(opts: T.Union[options.MutableKeyedOptionDictType, options.OptionStore], section: str) -> None:
        for key, opt in sorted(opts.items()):
            optdict = {'name': str(key), 'value': opt.value, 'section': section,
                       'machine': key.machine.get_lower_case_name() if coredata.optstore.is_per_machine_option(key) else 'any'}
            if isinstance(opt, options.UserStringOption):
                typestr = 'string'
            elif isinstance(opt, options.UserBooleanOption):
                typestr = 'boolean'
            elif isinstance(opt, options.UserComboOption):
                optdict['choices'] = opt.printable_choices()
                typestr = 'combo'
            elif isinstance(opt, options.UserUmaskOption):
                # do not print 0o22
                if isinstance(optdict['value'], int):
                    typestr = 'integer'
                    optdict['value'] = int(optdict['value'])
                else:
                    typestr = 'string'
            elif isinstance(opt, options.UserIntegerOption):
                typestr = 'integer'
            elif isinstance(opt, options.UserStringArrayOption):
                typestr = 'array'
                c = opt.printable_choices()
                if c:
                    optdict['choices'] = c
            else:
                raise RuntimeError('Unknown option type: ', repr(type(opt)))
            optdict['type'] = typestr
            optdict['description'] = opt.description
            optlist.append(optdict)

    add_keys(core_options, 'core')
    add_keys({k: v for k, v in coredata.optstore.items() if coredata.optstore.is_backend_option(k)}, 'backend')
    add_keys({k: v for k, v in coredata.optstore.items() if coredata.optstore.is_base_option(k)}, 'base')
    add_keys(
        {k: v for k, v in sorted(coredata.optstore.items(), key=lambda i: i[0].machine) if coredata.optstore.is_compiler_option(k)},
        'compiler',
    )
    add_keys(dir_options, 'directory')

    def project_option_key_to_introname(key: OptionKey) -> OptionKey:
        assert key.subproject is not None
        if key.subproject == '':
            return key.evolve(subproject=None)
        return key

    add_keys({project_option_key_to_introname(k): v
              for k, v in coredata.optstore.items() if coredata.optstore.is_project_option(k)}, 'user')
    add_keys(test_options, 'test')
    return optlist

def find_buildsystem_files_list(src_dir: str) -> T.List[str]:
    build_files = frozenset({'meson.build', 'meson.options', 'meson_options.txt'})
    # I feel dirty about this. But only slightly.
    filelist: T.List[str] = []
    for root, _, files in os.walk(src_dir):
        filelist.extend(os.path.relpath(os.path.join(root, f), src_dir)
                        for f in build_files.intersection(files))
    return filelist

def list_buildsystem_files(coredata: cdata.CoreData, builddata: build.Build, backend: backends.Backend) -> T.List[str]:
    src_dir = builddata.environment.get_source_dir()
    filelist = [PurePath(src_dir, x).as_posix() for x in builddata.def_files]
    return filelist

def list_compilers(coredata: cdata.CoreData, builddata: build.Build, backend: backends.Backend) -> T.Dict[str, T.Dict[str, T.Dict[str, str]]]:
    compilers: T.Dict[str, T.Dict[str, T.Dict[str, str]]] = {}
    for machine in ('host', 'build'):
        compilers[machine] = {}
        for language, compiler in getattr(coredata.compilers, machine).items():
            compilers[machine][language] = {
                'id': compiler.get_id(),
                'exelist': compiler.get_exelist(),
                'linker_exelist': compiler.get_linker_exelist(),
                'file_suffixes': compiler.file_suffixes,
                'default_suffix': compiler.get_default_suffix(),
                'version': compiler.version,
                'full_version': compiler.full_version,
                'linker_id': compiler.get_linker_id(),
            }
    return compilers

def list_deps_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[str, bool, T.List[str], UnknownValue]]]:
    result: T.List[T.Dict[str, T.Union[str, bool, T.List[str], UnknownValue]]] = []
    for i in intr.dependencies:
        result += [{
            'name': i.name,
            'required': i.required,
            'version': i.version,
            'has_fallback': i.has_fallback,
            'conditional': i.conditional,
        }]
    return result

def list_deps(coredata: cdata.CoreData, builddata: build.Build, backend: backends.Backend) -> T.List[T.Dict[str, T.Union[str, T.List[str]]]]:
    result: T.Dict[str, T.Dict[str, T.Union[str, T.List[str]]]] = {}

    def _src_to_str(src_file: T.Union[str, build.TargetSources, build.StructuredSources]) -> T.List[str]:
        if isinstance(src_file, str):
            return [src_file]
        if isinstance(src_file, mesonlib.File):
            return [src_file.absolute_path(backend.source_dir, backend.build_dir)]
        if isinstance(src_file, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)):
            return src_file.get_outputs()
        if isinstance(src_file, build.StructuredSources):
            return [f for s in src_file.as_list() for f in _src_to_str(s)]
        raise mesonlib.MesonBugException(f'Invalid file type {type(src_file)}.')

    def _create_result(d: Dependency) -> T.Dict[str, T.Any]:
        return {
            'name': d.name,
            'type': d.type_name,
            'version': d.get_version(),
            'compile_args': d.get_compile_args(),
            'link_args': d.get_link_args(),
            'include_directories': [i for idirs in d.get_include_dirs() for i in idirs.abs_string_list(backend.source_dir, backend.build_dir)],
            'sources': [f for s in d.get_sources() for f in _src_to_str(s)],
            'extra_files': [f for s in d.get_extra_files() for f in _src_to_str(s)],
            'dependencies': [e.name for e in d.ext_deps],
            'depends': [lib.get_id() for lib in getattr(d, 'libraries', [])],
            'meson_variables': d.meson_variables,
        }

    for d in coredata.deps.host.values():
        if d.found():
            result[d.name] = _create_result(d)

    return list(result.values())

def get_test_list(testdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
    result: T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]] = []
    for t in testdata:
        to: T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]] = {}
        if isinstance(t.fname, str):
            fname = [t.fname]
        else:
            fname = t.fname
        to['cmd'] = fname + t.cmd_args
        if isinstance(t.env, mesonlib.EnvironmentVariables):
            to['env'] = t.env.get_env({})
        else:
            to['env'] = t.env
        to['name'] = t.name
        to['workdir'] = t.workdir
        to['timeout'] = t.timeout
        to['suite'] = t.suite
        to['is_parallel'] = t.is_parallel
        to['priority'] = t.priority
        to['protocol'] = str(t.protocol)
        to['depends'] = t.depends
        to['extra_paths'] = t.extra_paths
        result.append(to)
    return result

def list_tests(coredata: cdata.CoreData, builddata: build.Build, backend: backends.Backend) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
    testdata = backend.create_test_serialisation(builddata.get_tests())
    return get_test_list(testdata)

def list_benchmarks(coredata: cdata.CoreData, builddata: build.Build, backend: backends.Backend) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
    benchdata = backend.create_test_serialisation(builddata.get_benchmarks())
    return get_test_list(benchdata)

def list_machines(coredata: cdata.CoreData, builddata: build.Build, backend: backends.Backend) -> T.Dict[str, T.Dict[str, T.Union[str, bool]]]:
    machines: T.Dict[str, T.Dict[str, T.Union[str, bool]]] = {}
    for m in ('host', 'build', 'target'):
        machine = getattr(builddata.environment.machines, m)
        machines[m] = dataclasses.asdict(machine)
        machines[m]['is_64_bit'] = machine.is_64_bit
        machines[m]['exe_suffix'] = machine.get_exe_suffix()
        machines[m]['object_suffix'] = machine.get_object_suffix()
    return machines

def list_projinfo(coredata: cdata.CoreData, builddata: build.Build, backend: backends.Backend) -> T.Dict[str, T.Union[str, T.List[str], T.List[T.Dict[str, str]]]]:
    result: T.Dict[str, T.Union[str, T.List[str], T.List[T.Dict[str, str]]]] = {
        'version': builddata.project_version,
        'descriptive_name': builddata.project_name,
        'license': builddata.dep_manifest[builddata.project_name].license,
        'license_files': [f[1].fname for f in builddata.dep_manifest[builddata.project_name].license_files],
        'subproject_dir': builddata.subproject_dir,
    }
    subprojects = []
    seen = set([''])
    for k, build_proj in itertools.chain(builddata.projects.host.items(),
                                         builddata.projects.build.items()):
        if k in seen:
            continue
        seen.add(k)
        c: T.Dict[str, str] = {
            'name': k,
            'version': build_proj.version,
            'descriptive_name': build_proj.name,
        }
        subprojects.append(c)
    result['subprojects'] = subprojects
    return result

def list_projinfo_from_source(intr: IntrospectionInterpreter) -> T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]:
    sourcedir = intr.source_root
    files = find_buildsystem_files_list(sourcedir)
    files = [os.path.normpath(x) for x in files]

    for i in intr.project_data['subprojects']:
        basedir = os.path.join(intr.subproject_dir, i['name'])
        i['buildsystem_files'] = [x for x in files if x.startswith(basedir)]
        files = [x for x in files if not x.startswith(basedir)]

    intr.project_data['buildsystem_files'] = files
    intr.project_data['subproject_dir'] = intr.subproject_dir
    return intr.project_data

def print_results(options: argparse.Namespace, results: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], indent: T.Optional[int]) -> int:
    if not results and not options.force_dict:
        print('No command specified')
        return 1
    elif len(results) == 1 and not options.force_dict:
        # Make to keep the existing output format for a single option
        print(json.dumps(results[0][1], indent=indent, cls=IntrospectionEncoder))
    else:
        out = {}
        for i in results:
            out[i[0]] = i[1]
        print(json.dumps(out, indent=indent, cls=IntrospectionEncoder))
    return 0

def get_infodir(builddir: T.Optional[str] = None) -> str:
    infodir = 'meson-info'
    if builddir is not None:
        infodir = os.path.join(builddir, infodir)
    return infodir

def get_info_file(infodir: str, kind: T.Optional[str] = None) -> str:
    return os.path.join(infodir,
                        'meson-info.json' if not kind else f'intro-{kind}.json')

def load_info_file(infodir: str, kind: T.Optional[str] = None) -> T.Any:
    with open(get_info_file(infodir, kind), encoding='utf-8') as fp:
        return json.load(fp)

@dataclasses.dataclass
class IntroCommand:
    desc: str
    func: T.Optional[T.Callable[[cdata.CoreData, build.Build, backends.Backend], T.Union[dict, list]]] = None
    no_bd: T.Optional[T.Callable[[IntrospectionInterpreter], T.Union[dict, list]]] = None

    def __post_init__(self) -> None:
        self.desc += '.'

INTRO_TYPES: T.Mapping[str, IntroCommand] = {
    'ast': IntroCommand('Dump the AST of the meson file', no_bd=dump_ast),
    'benchmarks': IntroCommand('List all benchmarks', func=list_benchmarks),
    'buildoptions': IntroCommand('List all build options', func=list_buildoptions, no_bd=list_buildoptions_from_source),
    'buildsystem_files': IntroCommand('List files that make up the build system', func=list_buildsystem_files),
    'compilers': IntroCommand('List used compilers', func=list_compilers),
    'dependencies': IntroCommand('List external dependencies', func=list_deps, no_bd=list_deps_from_source),
    'scan_dependencies': IntroCommand('Scan for dependencies used in the meson.build file', no_bd=list_deps_from_source),
    'installed': IntroCommand('List all installed files and directories', func=list_installed),
    'install_plan': IntroCommand('List all installed files and directories with their details', func=list_install_plan),
    'machines': IntroCommand('Information about host, build, and target machines', func=list_machines),
    'projectinfo': IntroCommand('Information about projects', func=list_projinfo, no_bd=list_projinfo_from_source),
    'targets': IntroCommand('List top level targets', func=list_targets, no_bd=list_targets_from_source),
    'tests': IntroCommand('List all unit tests', func=list_tests),
}

# Note: when adding arguments, please also add them to the completion
# scripts in $MESONSRC/data/shell-completions/
def add_arguments(parser: argparse.ArgumentParser) -> None:
    for key, val in INTRO_TYPES.items():
        flag = '--' + key.replace('_', '-')
        parser.add_argument(flag, action='store_true', dest=key, default=False, help=val.desc)

    parser.add_argument('--backend', choices=sorted(options.backendlist), dest='backend', default='ninja',
                        help='The backend to use for the --buildoptions introspection.')
    parser.add_argument('-a', '--all', action='store_true', dest='all', default=False,
                        help='Print all available information.')
    parser.add_argument('-i', '--indent', action='store_true', dest='indent', default=False,
                        help='Enable pretty printed JSON.')
    parser.add_argument('-f', '--force-object-output', action='store_true', dest='force_dict', default=False,
                        help='Always use the new JSON format for multiple entries (even for 0 and 1 introspection commands)')
    parser.add_argument('builddir', nargs='?', default='.', help='The build directory')

def run(options: argparse.Namespace) -> int:
    datadir = 'meson-private'
    infodir = get_infodir(options.builddir)
    if options.builddir is not None:
        datadir = os.path.join(options.builddir, datadir)
    indent = 4 if options.indent else None
    results: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]] = []

    # TODO: This if clause is undocumented.
    if os.path.basename(options.builddir) == environment.build_filename:
        sourcedir = '.' if options.builddir == environment.build_filename else options.builddir[:-len(environment.build_filename)]
        # Make sure that log entries in other parts of meson don't interfere with the JSON output
        with redirect_stdout(sys.stderr):
            backend = backends.get_backend_from_name(options.backend)
            intr = IntrospectionInterpreter(sourcedir, '', backend.name, visitors = [AstIDGenerator(), AstIndentationGenerator(), AstConditionLevel()])
            intr.analyze()

        for key, val in INTRO_TYPES.items():
            if (not options.all and not getattr(options, key, False)) or not val.no_bd:
                continue
            results += [(key, val.no_bd(intr))]
        return print_results(options, results, indent)

    try:
        raw = load_info_file(infodir)
        intro_vers = raw.get('introspection', {}).get('version', {}).get('full', '0.0.0')
    except FileNotFoundError:
        if not os.path.isdir(datadir) or not os.path.isdir(infodir):
            print('Current directory is not a meson build directory.\n'
                  'Please specify a valid build dir or change the working directory to it.')
        else:
            print('Introspection file {} does not exist.\n'
                  'It is also possible that the build directory was generated with an old\n'
                  'meson version. Please regenerate it in this case.'.format(get_info_file(infodir)))
        return 1

    vers_to_check = get_meson_introspection_required_version()
    for i in vers_to_check:
        if not mesonlib.version_compare(intro_vers, i):
            print('Introspection version {} is not supported. '
                  'The required version is: {}'
                  .format(intro_vers, ' and '.join(vers_to_check)))
            return 1

    # Extract introspection information from JSON
    for i, v in INTRO_TYPES.items():
        if not v.func:
            continue
        if not options.all and not getattr(options, i, False):
            continue
        try:
            results += [(i, load_info_file(infodir, i))]
        except FileNotFoundError:
            print('Introspection file {} does not exist.'.format(get_info_file(infodir, i)))
            return 1

    return print_results(options, results, indent)

updated_introspection_files: T.List[str] = []

def write_intro_info(intro_info: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], info_dir: str) -> None:
    for kind, data in intro_info:
        out_file = os.path.join(info_dir, f'intro-{kind}.json')
        tmp_file = os.path.join(info_dir, 'tmp_dump.json')
        with open(tmp_file, 'w', encoding='utf-8') as fp:
            json.dump(data, fp, indent=2)
            fp.flush() # Not sure if this is needed
        os.replace(tmp_file, out_file)
        updated_introspection_files.append(kind)

def generate_introspection_file(builddata: build.Build, backend: backends.Backend) -> None:
    coredata = builddata.environment.get_coredata()
    intro_info: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]] = []

    for key, val in INTRO_TYPES.items():
        if not val.func:
            continue
        intro_info += [(key, val.func(coredata, builddata, backend))]

    write_intro_info(intro_info, builddata.environment.info_dir)

def update_build_options(coredata: cdata.CoreData, info_dir: str) -> None:
    intro_info = [
        ('buildoptions', _list_buildoptions(coredata))
    ]

    write_intro_info(intro_info, info_dir)

def split_version_string(version: str) -> T.Dict[str, T.Union[str, int]]:
    vers_list = version.split('.')
    return {
        'full': version,
        'major': int(vers_list[0] if len(vers_list) > 0 else 0),
        'minor': int(vers_list[1] if len(vers_list) > 1 else 0),
        'patch': int(vers_list[2] if len(vers_list) > 2 else 0)
    }

def write_meson_info_file(builddata: build.Build, errors: list, build_files_updated: bool = False) -> None:
    info_dir = builddata.environment.info_dir
    info_file = get_meson_info_file(info_dir)
    intro_info = {}

    for i, v in INTRO_TYPES.items():
        if not v.func:
            continue
        intro_info[i] = {
            'file': f'intro-{i}.json',
            'updated': i in updated_introspection_files
        }

    info_data = {
        'meson_version': split_version_string(cdata.version),
        'directories': {
            'source': builddata.environment.get_source_dir(),
            'build': builddata.environment.get_build_dir(),
            'info': info_dir,
        },
        'introspection': {
            'version': split_version_string(get_meson_introspection_version()),
            'information': intro_info,
        },
        'build_files_updated': build_files_updated,
    }

    if errors:
        info_data['error'] = True
        info_data['error_list'] = [x if isinstance(x, str) else str(x) for x in errors]
    else:
        info_data['error'] = False

    # Write the data to disc
    tmp_file = os.path.join(info_dir, 'tmp_dump.json')
    with open(tmp_file, 'w', encoding='utf-8') as fp:
        json.dump(info_data, fp)
        fp.flush()
    os.replace(tmp_file, info_file)
