|
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
# Copyright 2019 The Meson development team
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
import subprocess
|
|
|
|
from pathlib import Path
|
|
|
|
import tempfile
|
|
|
|
import os
|
|
|
|
import shutil
|
|
|
|
import sys
|
|
|
|
|
|
|
|
from .run_tool import run_clang_tool, run_with_buffered_output
|
|
|
|
from ..environment import detect_clangtidy, detect_clangapply
|
|
|
|
import typing as T
|
|
|
|
|
|
|
|
async def run_clang_tidy(fname: Path, tidyexe: list, builddir: Path, fixesdir: T.Optional[Path]) -> int:
|
|
|
|
args = []
|
|
|
|
if fixesdir is not None:
|
|
|
|
handle, name = tempfile.mkstemp(prefix=fname.name + '.', suffix='.yaml', dir=fixesdir)
|
|
|
|
os.close(handle)
|
|
|
|
args.extend(['-export-fixes', name])
|
|
|
|
return await run_with_buffered_output(tidyexe + args + ['-quiet', '-p', str(builddir), str(fname)])
|
|
|
|
|
|
|
|
def run(args: T.List[str]) -> int:
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument('--fix', action='store_true')
|
scripts: make clang tools obey b_colorout
Right now, the clang-tidy and clang-format targets use the program default
and do not let b_colorout decide whether to colorize output.
However, the wrappers that run the tool are going to be changed to buffer
output, and that would disable colorization unconditionally. So pass
a --color option to the tools and use it when building the command line.
clang-format's -fcolor-diagnostics option simply does not work, and the
"right" (or at least working) option is --color which is undocumented.
--color is present all the way back to clang 10, but I digged into
clang-format's source code to figure out what's happening. The problem
is that -fcolor-diagnostics is a complete no-operation; in fact it is
a bool that is initialized to true. gdb shows:
(gdb) p ShowColors
$2 = {<llvm::cl::Option> = {
... <llvm::cl::opt_storage<bool, false, false>> = {Value = true, ... }, ...}
on entry to clang-format's main, meaning that specifying the option on
the command line does nothing at all.
To see how clang-format determines whether to use colors you need to look
at enters SMDiagnostic::print, which simply does
ColorMode Mode = ShowColors ? ColorMode::Auto : ColorMode::Disable;
showing once more that in fact the option cannot force-on the colors (
-fno-color-diagnostics instead works). Continuing in SMDiagnostic::print,
this RAII constructor would write the escape sequence to the terminal:
WithColor S(OS, raw_ostream::SAVEDCOLOR, true, false, Mode);
It ends up in WithColor::changeColor, which does
if (colorsEnabled())
OS.changeColor(Color, Bold, BG);
Digging further down, colorsEnabled() is where the Mode member is consulted:
bool WithColor::colorsEnabled() {
switch (Mode) {
case ColorMode::Enable:
return true;
case ColorMode::Disable:
return false;
case ColorMode::Auto:
return AutoDetectFunction(OS);
}
llvm_unreachable("All cases handled above.");
}
and the "AutoDetectFunction" is
static bool DefaultAutoDetectFunction(const raw_ostream &OS) {
return *UseColor == cl::BOU_UNSET ? OS.has_colors()
: *UseColor == cl::BOU_TRUE;
}
UseColor is controlled by the "--color" option, so if that option was
unset you go to OS.has_colors() even in the presence of -fcolor-diagnostics.
This has been around for over 5 years in clang-format, and it was present
even earlier, so use it in meson as well.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
3 months ago
|
|
|
parser.add_argument('--color', default='always')
|
|
|
|
parser.add_argument('sourcedir')
|
|
|
|
parser.add_argument('builddir')
|
|
|
|
options = parser.parse_args(args)
|
|
|
|
|
|
|
|
srcdir = Path(options.sourcedir)
|
|
|
|
builddir = Path(options.builddir)
|
|
|
|
|
|
|
|
tidyexe = detect_clangtidy()
|
|
|
|
if not tidyexe:
|
|
|
|
print(f'Could not execute clang-tidy "{" ".join(tidyexe)}"')
|
|
|
|
return 1
|
|
|
|
|
scripts: make clang tools obey b_colorout
Right now, the clang-tidy and clang-format targets use the program default
and do not let b_colorout decide whether to colorize output.
However, the wrappers that run the tool are going to be changed to buffer
output, and that would disable colorization unconditionally. So pass
a --color option to the tools and use it when building the command line.
clang-format's -fcolor-diagnostics option simply does not work, and the
"right" (or at least working) option is --color which is undocumented.
--color is present all the way back to clang 10, but I digged into
clang-format's source code to figure out what's happening. The problem
is that -fcolor-diagnostics is a complete no-operation; in fact it is
a bool that is initialized to true. gdb shows:
(gdb) p ShowColors
$2 = {<llvm::cl::Option> = {
... <llvm::cl::opt_storage<bool, false, false>> = {Value = true, ... }, ...}
on entry to clang-format's main, meaning that specifying the option on
the command line does nothing at all.
To see how clang-format determines whether to use colors you need to look
at enters SMDiagnostic::print, which simply does
ColorMode Mode = ShowColors ? ColorMode::Auto : ColorMode::Disable;
showing once more that in fact the option cannot force-on the colors (
-fno-color-diagnostics instead works). Continuing in SMDiagnostic::print,
this RAII constructor would write the escape sequence to the terminal:
WithColor S(OS, raw_ostream::SAVEDCOLOR, true, false, Mode);
It ends up in WithColor::changeColor, which does
if (colorsEnabled())
OS.changeColor(Color, Bold, BG);
Digging further down, colorsEnabled() is where the Mode member is consulted:
bool WithColor::colorsEnabled() {
switch (Mode) {
case ColorMode::Enable:
return true;
case ColorMode::Disable:
return false;
case ColorMode::Auto:
return AutoDetectFunction(OS);
}
llvm_unreachable("All cases handled above.");
}
and the "AutoDetectFunction" is
static bool DefaultAutoDetectFunction(const raw_ostream &OS) {
return *UseColor == cl::BOU_UNSET ? OS.has_colors()
: *UseColor == cl::BOU_TRUE;
}
UseColor is controlled by the "--color" option, so if that option was
unset you go to OS.has_colors() even in the presence of -fcolor-diagnostics.
This has been around for over 5 years in clang-format, and it was present
even earlier, so use it in meson as well.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
3 months ago
|
|
|
if options.color == 'always' or options.color == 'auto' and sys.stdout.isatty():
|
|
|
|
tidyexe += ['--use-color']
|
|
|
|
|
|
|
|
fixesdir: T.Optional[Path] = None
|
|
|
|
if options.fix:
|
|
|
|
applyexe = detect_clangapply()
|
|
|
|
if not applyexe:
|
|
|
|
print(f'Could not execute clang-apply-replacements "{" ".join(applyexe)}"')
|
|
|
|
return 1
|
|
|
|
|
|
|
|
fixesdir = builddir / 'meson-private' / 'clang-tidy-fix'
|
|
|
|
if fixesdir.is_dir():
|
|
|
|
shutil.rmtree(fixesdir)
|
|
|
|
elif fixesdir.exists():
|
|
|
|
fixesdir.unlink()
|
|
|
|
fixesdir.mkdir(parents=True)
|
|
|
|
|
|
|
|
tidyret = run_clang_tool('clang-tidy', srcdir, builddir, run_clang_tidy, tidyexe, builddir, fixesdir)
|
|
|
|
if fixesdir is not None:
|
|
|
|
print('Applying fix-its...')
|
|
|
|
applyret = subprocess.run(applyexe + ['-format', '-style=file', '-ignore-insert-conflict', fixesdir]).returncode
|
|
|
|
|
|
|
|
if tidyret != 0:
|
|
|
|
print('Errors encountered while running clang-tidy', file=sys.stderr)
|
|
|
|
return tidyret
|
|
|
|
if fixesdir is not None and applyret != 0:
|
|
|
|
print('Errors encountered while running clang-apply-replacements', file=sys.stderr)
|
|
|
|
return applyret
|
|
|
|
return 0
|