xref: /llvm-project/cross-project-tests/debuginfo-tests/dexter/dex/tools/ToolBase.py (revision f98ee40f4b5d7474fc67e82824bf6abbaedb7b1c)
1# DExTer : Debugging Experience Tester
2# ~~~~~~   ~         ~~         ~   ~~
3#
4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5# See https://llvm.org/LICENSE.txt for license information.
6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7"""Base class for all subtools."""
8
9import abc
10import os
11import tempfile
12
13from dex import __version__
14from dex.utils import ExtArgParse
15from dex.utils import PrettyOutput
16from dex.utils.ReturnCode import ReturnCode
17
18
19class ToolBase(object, metaclass=abc.ABCMeta):
20    def __init__(self, context):
21        self.context = context
22        self.parser = None
23
24    @abc.abstractproperty
25    def name(self):
26        pass
27
28    @abc.abstractmethod
29    def add_tool_arguments(self, parser, defaults):
30        pass
31
32    def parse_command_line(self, args):
33        """Define two parsers: pparser and self.parser.
34        pparser deals with args that need to be parsed prior to any of those of
35        self.parser.  For example, any args which may affect the state of
36        argparse error output.
37        """
38
39        class defaults(object):
40            pass
41
42        pparser = ExtArgParse.ExtArgumentParser(
43            self.context, add_help=False, prog=self.name
44        )
45
46        pparser.add_argument(
47            "--no-color-output",
48            action="store_true",
49            default=False,
50            help="do not use colored output on stdout/stderr",
51        )
52        pparser.add_argument(
53            "--time-report",
54            action="store_true",
55            default=False,
56            help="display timing statistics",
57        )
58
59        self.parser = ExtArgParse.ExtArgumentParser(
60            self.context, parents=[pparser], prog=self.name
61        )
62        self.parser.add_argument(
63            "-v",
64            "--verbose",
65            action="store_true",
66            default=False,
67            help="enable verbose output (overrides --no-warnings)",
68        )
69        self.parser.add_argument(
70            "-V",
71            "--version",
72            action="store_true",
73            default=False,
74            help="display the DExTer version and exit",
75        )
76        self.parser.add_argument(
77            "-w",
78            "--no-warnings",
79            action="store_true",
80            default=False,
81            help="suppress warning output",
82        )
83        self.parser.add_argument(
84            "--unittest",
85            type=str,
86            choices=["off", "show-failures", "show-all"],
87            default="off",
88            help="run the DExTer codebase unit tests",
89        )
90
91        suppress = ExtArgParse.SUPPRESS  # pylint: disable=no-member
92        self.parser.add_argument(
93            "--colortest", action="store_true", default=False, help=suppress
94        )
95        self.parser.add_argument(
96            "--error-debug", action="store_true", default=False, help=suppress
97        )
98        defaults.working_directory = os.path.join(tempfile.gettempdir(), "dexter")
99        self.parser.add_argument(
100            "--indent-timer-level", type=int, default=1, help=suppress
101        )
102        self.parser.add_argument(
103            "--working-directory",
104            type=str,
105            metavar="<file>",
106            default=None,
107            display_default=defaults.working_directory,
108            help="location of working directory",
109        )
110        self.parser.add_argument(
111            "--save-temps",
112            action="store_true",
113            default=False,
114            help="save temporary files",
115        )
116
117        self.add_tool_arguments(self.parser, defaults)
118
119        # If an error is encountered during pparser, show the full usage text
120        # including self.parser options. Strip the preceding 'usage: ' to avoid
121        # having it appear twice.
122        pparser.usage = self.parser.format_usage().lstrip("usage: ")
123
124        options, args = pparser.parse_known_args(args)
125
126        if options.no_color_output:
127            PrettyOutput.stdout.color_enabled = False
128            PrettyOutput.stderr.color_enabled = False
129
130        options = self.parser.parse_args(args, namespace=options)
131        return options, defaults
132
133    def handle_base_options(self, defaults):
134        self.handle_options(defaults)
135
136        options = self.context.options
137
138        if options.working_directory is None:
139            options.working_directory = defaults.working_directory
140
141    @abc.abstractmethod
142    def handle_options(self, defaults):
143        pass
144
145    @abc.abstractmethod
146    def go(self) -> ReturnCode:
147        pass
148