Eric Snow | e4c431e | 2019-10-18 19:00:04 -0700 | [diff] [blame] | 1 | import os.path |
| 2 | |
| 3 | from c_analyzer.common import files |
| 4 | from c_analyzer.common.info import UNKNOWN, ID |
| 5 | from c_analyzer.variables import find as _common |
| 6 | |
| 7 | from . import SOURCE_DIRS, PYTHON, REPO_ROOT |
| 8 | from .known import ( |
| 9 | from_file as known_from_file, |
| 10 | DATA_FILE as KNOWN_FILE, |
| 11 | ) |
| 12 | from .supported import ( |
| 13 | ignored_from_file, IGNORED_FILE, is_supported, _is_object, |
| 14 | ) |
| 15 | |
| 16 | # XXX need tests: |
| 17 | # * vars_from_binary() |
| 18 | # * vars_from_source() |
| 19 | # * supported_vars() |
| 20 | |
| 21 | |
| 22 | def _handle_id(filename, funcname, name, *, |
| 23 | _relpath=os.path.relpath, |
| 24 | ): |
| 25 | filename = _relpath(filename, REPO_ROOT) |
| 26 | return ID(filename, funcname, name) |
| 27 | |
| 28 | |
| 29 | def vars_from_binary(*, |
| 30 | known=KNOWN_FILE, |
| 31 | _known_from_file=known_from_file, |
| 32 | _iter_files=files.iter_files_by_suffix, |
| 33 | _iter_vars=_common.vars_from_binary, |
| 34 | ): |
| 35 | """Yield a Variable for each found Symbol. |
| 36 | |
| 37 | Details are filled in from the given "known" variables and types. |
| 38 | """ |
| 39 | if isinstance(known, str): |
| 40 | known = _known_from_file(known) |
| 41 | dirnames = SOURCE_DIRS |
| 42 | suffixes = ('.c',) |
| 43 | filenames = _iter_files(dirnames, suffixes) |
| 44 | # XXX For now we only use known variables (no source lookup). |
| 45 | filenames = None |
| 46 | yield from _iter_vars(PYTHON, |
| 47 | known=known, |
| 48 | filenames=filenames, |
| 49 | handle_id=_handle_id, |
| 50 | check_filename=(lambda n: True), |
| 51 | ) |
| 52 | |
| 53 | |
| 54 | def vars_from_source(*, |
| 55 | preprocessed=None, |
| 56 | known=KNOWN_FILE, |
| 57 | _known_from_file=known_from_file, |
| 58 | _iter_files=files.iter_files_by_suffix, |
| 59 | _iter_vars=_common.vars_from_source, |
| 60 | ): |
| 61 | """Yield a Variable for each declaration in the raw source code. |
| 62 | |
| 63 | Details are filled in from the given "known" variables and types. |
| 64 | """ |
| 65 | if isinstance(known, str): |
| 66 | known = _known_from_file(known) |
| 67 | dirnames = SOURCE_DIRS |
| 68 | suffixes = ('.c',) |
| 69 | filenames = _iter_files(dirnames, suffixes) |
| 70 | yield from _iter_vars(filenames, |
| 71 | preprocessed=preprocessed, |
| 72 | known=known, |
| 73 | handle_id=_handle_id, |
| 74 | ) |
| 75 | |
| 76 | |
| 77 | def supported_vars(*, |
| 78 | known=KNOWN_FILE, |
| 79 | ignored=IGNORED_FILE, |
| 80 | skip_objects=False, |
| 81 | _known_from_file=known_from_file, |
| 82 | _ignored_from_file=ignored_from_file, |
| 83 | _iter_vars=vars_from_binary, |
| 84 | _is_supported=is_supported, |
| 85 | ): |
| 86 | """Yield (var, is supported) for each found variable.""" |
| 87 | if isinstance(known, str): |
| 88 | known = _known_from_file(known) |
| 89 | if isinstance(ignored, str): |
| 90 | ignored = _ignored_from_file(ignored) |
| 91 | |
| 92 | for var in _iter_vars(known=known): |
| 93 | if not var.isglobal: |
| 94 | continue |
| 95 | elif var.vartype == UNKNOWN: |
| 96 | yield var, None |
| 97 | # XXX Support proper filters instead. |
| 98 | elif skip_objects and _is_object(found.vartype): |
| 99 | continue |
| 100 | else: |
| 101 | yield var, _is_supported(var, ignored, known) |