def check_file(self):
        """Perform all necessary checks on our file (including rulific ones).

        Raise FileCheckerError if an error is detected.

        :return: None.
        :rtype: None
        """
        log_info("Checking style of `%s' (%s)"
                 % (self.filename, self.file_type))

        # Build the error message into a list. And then, at the end of
        # this function, if it turns out we got at least one issue,
        # raise it via FileCheckerError.
        err_msgs = []

        # First, run the external checker...
        external_checker_err_msg = self.run_external_checker()
        if external_checker_err_msg is not None:
            # Stop immediately if the external checker detected some
            # errors.  We could continue, and run the rest of the
            # tests, but cvs_check, the previous style checker,
            # wasn't doing that, so we don't either so as to be
            # consistent with the traditional behavior.
            raise FileCheckerError(external_checker_err_msg)

        # First, feed line-by-line the contents of the file to each
        # rulific checker.
        with open(self.filename) as f:
            for lineno, line in enumerate(f, 1):
                eol = get_eol(line)
                line = line[:-len(eol or '')]
                for rulific_checker in self.my_rulific_checkers:
                    rulific_checker.process_line(lineno, line, eol)

        # Merge all the result of the line-by-line checking, currently
        # stored in each rulific checker, into a combined dictionary,
        # where keys are still line numbers, but the value is a list
        # of error messages applying to that line number.
        all_linenos = sorted(
            set().union(*(rulific_checker.errors_found.keys()
                          for rulific_checker in self.my_rulific_checkers)))
        for lineno in all_linenos:
            for rulific_checker in self.my_rulific_checkers:
                if lineno in rulific_checker.errors_found:
                    err_msgs.append('%s:%d: %s'
                                    % (self.filename, lineno,
                                       rulific_checker.errors_found[lineno]))

        for rulific_checker in self.my_rulific_checkers:
            global_check_err_msg = rulific_checker.global_check()
            if global_check_err_msg:
                err_msgs.append(global_check_err_msg)

        if err_msgs:
            raise FileCheckerError(*err_msgs)
Beispiel #2
0
    def run_external_checker(self):
        file_type = self.file_type

        cmd = [
            'gcc',
            '-c',
            '-gnats',
            '-gnatm20',
            # Set "-x ada" so that we can style check Ada sources even
            # if their extension is not automatically identified by GCC.
            '-x',
            'ada',
        ]

        # Base options: use GNAT style

        if file_type in (RT_SPEC, RT_BODY):
            # Set GNAT mode for runtime files only (changes legality and
            # semantics, and sets more restrictive style rules).
            # Note: This also enables language extensions.
            cmd.append('-gnatg')
        else:
            # Enable GNAT style checks, GNAT warnings, and treat warnings
            # and style messages as errors.
            cmd.extend(['-gnatyg', '-gnatw.g', '-gnatwe'])

        if 'gnatx' in self.config.style_checks_options:
            cmd.append('-gnatX')

        # Set language version: by default enable Ada 2012, except for
        # compiler units (which must be Ada 95 for bootstrap). Can be
        # overridden using flags gnat95 and gnat05. (Note that flag
        # "gnat12" has no effect since this is now the default).

        if file_type in (RT_SPEC, RT_BODY):
            # Language version already set by -gnatg for runtime units
            pass
        elif 'gnatx' in self.config.style_checks_options:
            # Language version already set by -gnatX
            pass
        elif file_type == COMPILER_CORE or \
                'gnat95' in self.config.style_checks_options:
            cmd.append('-gnat95')
        elif 'gnat05' in self.config.style_checks_options:
            cmd.append('-gnat05')
        else:
            cmd.append('-gnat12')

        # Set preprocessing data file.
        cmd.append('-gnatep=' + self.config.ada_preprocessing_filename)

        cmd.append(self.filename)

        # Run GCC with some some critical environment variables unset.
        BANNED_ENV_VARS = ('GCC_EXEC_PREFIX', 'GCC_INSTALL_DIRECTORY',
                           'GCC_INCLUDE_DIR', 'GCC_ROOT', 'GNAT_ROOT',
                           'BINUTILS_ROOT')
        gcc_env = {
            var_name: value
            for var_name, value in os.environ.items()
            if var_name not in BANNED_ENV_VARS
        }

        try:
            log_info('Running: %s' % command_line_image(cmd), 2)
            p = Run(cmd, env=gcc_env)
            if p.status != 0 or p.out:
                return p.out
        except OSError as e:
            return 'Failed to run %s: %s' % (cmd[0], e)
Beispiel #3
0
    def run_external_checker(self):
        file_type = self.file_type

        cmd = [
            "gcc",
            "-c",
            "-gnats",
            "-gnatm20",
            # Set "-x ada" so that we can style check Ada sources even
            # if their extension is not automatically identified by GCC.
            "-x",
            "ada",
        ]

        # Base options: use GNAT style

        if file_type in (RT_SPEC, RT_BODY):
            # Set GNAT mode for runtime files only (changes legality and
            # semantics, and sets more restrictive style rules).
            #
            # Note: -gnatg normally also enables language extensions
            # (i.e. -gnatX), but it only does so when it recognizes
            # the unit's filename. Since we also store implementation
            # variations of the same runtime unit inside files whose name
            # do not always match the normal filename naming scheme
            # (e.g. "a-except__zfp.adb"), we force -gnatX to ensure
            # extensions are consistently used across all GNAT runtime
            # sources.
            #
            # Note also that the compiler hardcodes the language version
            # it uses when compiling the runtime units, so there is no point
            # in trying to force a different version with a command-line
            # switch, the compiler just ignores them (see T618-047 for
            # confirmation of that).
            cmd.extend(["-gnatg", "-gnatX"])
        else:
            # Enable GNAT style checks, GNAT warnings, and treat warnings
            # and style messages as errors.
            cmd.extend(["-gnatyg", "-gnatw.g", "-gnatwe"])

        # The "gnat" repository needs specific treatment because we want
        # to allow building GNAT without requiring too recent a compiler.

        if file_type in (RT_SPEC, RT_BODY):
            # Language version already set by -gnatg for runtime units
            pass
        elif file_type == COMPILER_CORE:
            cmd.append("-gnat12")

        # For all other repositories, allow Ada 2012 by default, except
        # explicity overriden by the repository.

        elif "gnatx" in self.config.style_checks_options:
            cmd.append("-gnatX")
        elif "gnat95" in self.config.style_checks_options:
            cmd.append("-gnat95")
        elif "gnat05" in self.config.style_checks_options:
            cmd.append("-gnat05")
        elif "gnat12" in self.config.style_checks_options:
            cmd.append("-gnat12")
        elif "gnat2020" in self.config.style_checks_options:
            cmd.append("-gnat2020")
        else:
            cmd.append("-gnat2020")

        # Set preprocessing data file.
        cmd.append("-gnatep=" + self.config.ada_preprocessing_filename)

        cmd.append(self.filename)

        # Run GCC with some some critical environment variables unset.
        BANNED_ENV_VARS = (
            "GCC_EXEC_PREFIX",
            "GCC_INSTALL_DIRECTORY",
            "GCC_INCLUDE_DIR",
            "GCC_ROOT",
            "GNAT_ROOT",
            "BINUTILS_ROOT",
        )
        gcc_env = {
            var_name: value
            for var_name, value in os.environ.items()
            if var_name not in BANNED_ENV_VARS
        }

        try:
            log_info("Running: %s" % command_line_image(cmd), 2)
            p = Run(cmd, env=gcc_env)
            if p.status != 0 or p.out:
                return p.out
        except OSError as e:
            return "Failed to run %s: %s" % (cmd[0], e)