# Copyright 2014-2016 The Meson development team

# 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.
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 collections
import dataclasses
import json
import os
from pathlib import Path, PurePath
import sys
import typing as T

from . import build, mesonlib, coredata as cdata
from .ast import IntrospectionInterpreter, BUILD_TARGET_FUNCTIONS, AstConditionLevel, AstIDGenerator, AstIndentationGenerator, AstJSONPrinter
from .backend import backends
from .dependencies import Dependency
from . import environment
from .interpreterbase import ObjectHolder
from .mesonlib import OptionKey
from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode

if T.TYPE_CHECKING:
    import argparse

    from .interpreter import Interpreter
    from .mparser import BaseNode

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']

class IntroCommand:
    def __init__(self,
                 desc: str,
                 func: T.Optional[T.Callable[[], T.Union[dict, list]]] = None,
                 no_bd: T.Optional[T.Callable[[IntrospectionInterpreter], T.Union[dict, list]]] = None) -> None:
        self.desc = desc + '.'
        self.func = func
        self.no_bd = no_bd

def get_meson_introspection_types(coredata: T.Optional[cdata.CoreData] = None,
                                  builddata: T.Optional[build.Build] = None,
                                  backend: T.Optional[backends.Backend] = None,
                                  sourcedir: T.Optional[str] = None) -> 'T.Mapping[str, IntroCommand]':
    if backend and builddata:
        benchmarkdata = backend.create_test_serialisation(builddata.get_benchmarks())
        testdata = backend.create_test_serialisation(builddata.get_tests())
        installdata = backend.create_install_data()
        interpreter = backend.interpreter
    else:
        benchmarkdata = testdata = installdata = None

    # Enforce key order for argparse
    return collections.OrderedDict([
        ('ast', IntroCommand('Dump the AST of the meson file', no_bd=dump_ast)),
        ('benchmarks', IntroCommand('List all benchmarks', func=lambda: list_benchmarks(benchmarkdata))),
        ('buildoptions', IntroCommand('List all build options', func=lambda: list_buildoptions(coredata), no_bd=list_buildoptions_from_source)),
        ('buildsystem_files', IntroCommand('List files that make up the build system', func=lambda: list_buildsystem_files(builddata, interpreter))),
        ('compilers', IntroCommand('List used compilers', func=lambda: list_compilers(coredata))),
        ('dependencies', IntroCommand('List external dependencies', func=lambda: list_deps(coredata, backend), 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=lambda: list_installed(installdata))),
        ('install_plan', IntroCommand('List all installed files and directories with their details', func=lambda: list_install_plan(installdata))),
        ('machines', IntroCommand('Information about host, build, and target machines', func=lambda: list_machines(builddata))),
        ('projectinfo', IntroCommand('Information about projects', func=lambda: list_projinfo(builddata), no_bd=list_projinfo_from_source)),
        ('targets', IntroCommand('List top level targets', func=lambda: list_targets(builddata, installdata, backend), no_bd=list_targets_from_source)),
        ('tests', IntroCommand('List all unit tests', func=lambda: list_tests(testdata))),
    ])

def add_arguments(parser: argparse.ArgumentParser) -> None:
    intro_types = get_meson_introspection_types()
    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(cdata.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 dump_ast(intr: IntrospectionInterpreter) -> T.Dict[str, T.Any]:
    printer = AstJSONPrinter()
    intr.ast.accept(printer)
    return printer.result

def list_installed(installdata: backends.InstallData) -> T.Dict[str, str]:
    res = {}
    if installdata is not None:
        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(installdata: backends.InstallData) -> T.Dict[str, T.Dict[str, T.Dict[str, T.Optional[str]]]]:
    plan = {
        'targets': {
            os.path.join(installdata.build_dir, target.fname): {
                'destination': target.out_name,
                'tag': target.tag or None,
            }
            for target in installdata.targets
        },
    }  # type: T.Dict[str, T.Dict[str, T.Dict[str, T.Optional[str]]]]
    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,
            }

            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.get_option(OptionKey('layout')) == 'flat':
        return 'meson-out'
    else:
        return subdir

def list_targets_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]:
    tlist = []  # type: T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]
    root_dir = Path(intr.source_root)

    def nodes_to_paths(node_list: T.List[BaseNode]) -> T.List[Path]:
        res = []  # type: T.List[Path]
        for n in node_list:
            args = []  # type: T.List[BaseNode]
            if isinstance(n, FunctionNode):
                args = list(n.args.arguments)
                if n.func_name in BUILD_TARGET_FUNCTIONS:
                    args.pop(0)
            elif isinstance(n, ArrayNode):
                args = n.args.arguments
            elif isinstance(n, ArgumentNode):
                args = n.arguments
            for j in args:
                if isinstance(j, StringNode):
                    assert isinstance(j.value, str)
                    res += [Path(j.value)]
                elif isinstance(j, str):
                    res += [Path(j)]
        res = [root_dir / i['subdir'] / x for x in res]
        res = [x.resolve() for x in res]
        return res

    for i in intr.targets:
        sources = nodes_to_paths(i['sources'])
        extra_f = nodes_to_paths(i['extra_files'])
        outdir = get_target_dir(intr.coredata, i['subdir'])

        tlist += [{
            'name': i['name'],
            'id': i['id'],
            'type': i['type'],
            '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',
                'compiler': [],
                'parameters': [],
                'sources': [str(x) for x in sources],
                'generated_sources': []
            }],
            'depends': [],
            'extra_files': [str(x) for x in extra_f],
            'subproject': None, # Subprojects are not supported
            'installed': i['installed']
        }]

    return tlist

def list_targets(builddata: build.Build, installdata: backends.InstallData, backend: backends.Backend) -> T.List[T.Any]:
    tlist = []  # type: 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 = {}
    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.subdir)
        t = {
            'name': target.get_basename(),
            'id': idname,
            'type': target.get_typename(),
            'defined_in': os.path.normpath(os.path.join(src_dir, target.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 installdata and 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_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 = []  # type: T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]
    subprojects = subprojects or []

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

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

    def add_keys(options: 'cdata.KeyedOptionDictType', section: str) -> None:
        for key, opt in sorted(options.items()):
            optdict = {'name': str(key), 'value': opt.value, 'section': section,
                       'machine': key.machine.get_lower_case_name() if coredata.is_per_machine_option(key) else 'any'}
            if isinstance(opt, cdata.UserStringOption):
                typestr = 'string'
            elif isinstance(opt, cdata.UserBooleanOption):
                typestr = 'boolean'
            elif isinstance(opt, cdata.UserComboOption):
                optdict['choices'] = opt.choices
                typestr = 'combo'
            elif isinstance(opt, cdata.UserIntegerOption):
                typestr = 'integer'
            elif isinstance(opt, cdata.UserArrayOption):
                typestr = 'array'
                if opt.choices:
                    optdict['choices'] = opt.choices
            else:
                raise RuntimeError("Unknown option type")
            optdict['type'] = typestr
            optdict['description'] = opt.description
            optlist.append(optdict)

    add_keys(core_options, 'core')
    add_keys({k: v for k, v in coredata.options.items() if k.is_backend()}, 'backend')
    add_keys({k: v for k, v in coredata.options.items() if k.is_base()}, 'base')
    add_keys(
        {k: v for k, v in sorted(coredata.options.items(), key=lambda i: i[0].machine) if k.is_compiler()},
        'compiler',
    )
    add_keys(dir_options, 'directory')
    add_keys({k: v for k, v in coredata.options.items() if k.is_project()}, '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(builddata: build.Build, interpreter: Interpreter) -> T.List[str]:
    src_dir = builddata.environment.get_source_dir()
    filelist = list(interpreter.get_build_def_files())
    filelist = [PurePath(src_dir, x).as_posix() for x in filelist]
    return filelist

def list_compilers(coredata: cdata.CoreData) -> 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]]]:
    result = []  # type: T.List[T.Dict[str, T.Union[str, bool]]]
    for i in intr.dependencies:
        keys = [
            'name',
            'required',
            'version',
            'has_fallback',
            'conditional',
        ]
        result += [{k: v for k, v in i.items() if k in keys}]
    return result

def list_deps(coredata: cdata.CoreData, 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[mesonlib.FileOrString, build.CustomTarget, build.StructuredSources, build.CustomTargetIndex, build.GeneratedList]) -> 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, varname: T.Optional[str] = None) -> 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.to_string_list(backend.source_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': [varname] if varname else [],
        }

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

    for varname, holder in backend.interpreter.variables.items():
        if isinstance(holder, ObjectHolder):
            d = holder.held_object
            if isinstance(d, Dependency) and d.found():
                if d.name in result:
                    T.cast(T.List[str], result[d.name]['meson_variables']).append(varname)
                else:
                    result[d.name] = _create_result(d, varname)

    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 = []  # type: T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]
    for t in testdata:
        to = {}  # type: 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, build.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(testdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
    return get_test_list(testdata)

def list_benchmarks(benchdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
    return get_test_list(benchdata)

def list_machines(builddata: build.Build) -> 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(builddata: build.Build) -> T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]:
    result = {'version': builddata.project_version,
              'descriptive_name': builddata.project_name,
              'subproject_dir': builddata.subproject_dir}    # type: T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]
    subprojects = []
    for k, v in builddata.subprojects.items():
        c = {'name': k,
             'version': v,
             'descriptive_name': builddata.projects.get(k)}  # type: T.Dict[str, str]
        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: 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))
    else:
        out = {}
        for i in results:
            out[i[0]] = i[1]
        print(json.dumps(out, indent=indent))
    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)

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 = []  # type: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]]
    sourcedir = '.' if options.builddir == 'meson.build' else options.builddir[:-11]
    intro_types = get_meson_introspection_types(sourcedir=sourcedir)

    if 'meson.build' in [os.path.basename(options.builddir), options.builddir]:
        # 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)
            assert backend is not None
            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 = []  # type: 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)
            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_types = get_meson_introspection_types(coredata=coredata, builddata=builddata, backend=backend)
    intro_info = []  # type: 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())]

    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_types = get_meson_introspection_types()
    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)
