Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions analyzer/codechecker_analyzer/cli/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -1012,13 +1012,15 @@ def is_checker_config_valid(

def get_affected_file_paths(
file_filters: List[str],
compile_commands: tu_collector.CompilationDB
compile_commands: tu_collector.CompilationDB,
jobs: int
) -> List[str]:
"""
Returns a list of source files for existing header file otherwise returns
with the same file path expression.
"""
file_paths = [] # Use list to keep the order of the file paths.
dependencies: tu_collector.Dependencies = collections.defaultdict(set)
for file_filter in file_filters:
file_paths.append(str(Path(file_filter).resolve())
if '*' not in file_filter else file_filter)
Expand All @@ -1027,7 +1029,7 @@ def get_affected_file_paths(
file_filter.endswith(header_file_extensions):
LOG.info("Get dependent source files for '%s'...", file_filter)
dependent_sources = tu_collector.get_dependent_sources(
compile_commands, file_filter)
compile_commands, file_filter, dependencies, jobs)

LOG.info("Get dependent source files for '%s' done.", file_filter)
LOG.debug("Dependent source files: %s",
Expand All @@ -1046,7 +1048,7 @@ def __get_skip_handlers(args, compile_commands) -> SkipListHandlers:
skip_handlers = SkipListHandlers()
if 'files' in args:
source_file_paths = get_affected_file_paths(
args.files, compile_commands)
args.files, compile_commands, args.jobs)

# Creates a skip file where all source files will be skipped except
# the given source files and all the header files.
Expand Down
41 changes: 29 additions & 12 deletions tools/tu_collector/tu_collector/tu_collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@
import subprocess
import sys
import zipfile
from multiprocessing import Pool
from shutil import which

from pathlib import Path
from typing import Iterable, Iterator, List, Optional, Set, Tuple, Union
from typing import Dict, Iterable, Iterator, List, Optional, Set, Tuple, Union

if sys.version_info >= (3, 8):
from typing import TypedDict # pylint: disable=no-name-in-module
Expand All @@ -56,6 +57,7 @@ class CompileAction(TypedDict):


CompilationDB = List[CompileAction]
Dependencies = Dict[str, Set[str]]


def __random_string(length: int) -> str:
Expand Down Expand Up @@ -472,21 +474,36 @@ def zip_tu_files(
json.dumps(compilation_database, indent=2))


def __get_dependent_headers_for_build_action(build_action: CompileAction
) -> Tuple[str, Set[str]]:
""" Return the source file and dependent headers for a build action. """
files, _ = get_dependent_headers(
build_action['command'],
build_action['directory'])

source_file = os.path.join(build_action['directory'],
build_action['file'])
return source_file, files


def get_dependent_sources(
compilation_db: CompilationDB,
header_path: Optional[str] = None
header_path: Optional[str] = None,
dependencies: Optional[Dependencies] = None,
jobs: Optional[int] = None
) -> Set[str]:
""" Get dependencies for each files in each translation unit. """
dependencies = collections.defaultdict(set)
for build_action in compilation_db:
files, _ = get_dependent_headers(
build_action['command'],
build_action['directory'])

source_file = os.path.join(build_action['directory'],
build_action['file'])
for f in files:
dependencies[f].add(source_file)
if dependencies is None:
dependencies = collections.defaultdict(set)
if jobs is None:
jobs = 1
if not dependencies:
with Pool(jobs) as p:
results = list(p.map(__get_dependent_headers_for_build_action,
compilation_db))
for source_file, files in results:
for f in files:
dependencies[f].add(source_file)

pattern = None
if header_path:
Expand Down
Loading