1# This file provides common utility functions for the test suite.
2
3import os
4HAS_FSPATH = hasattr(os, 'fspath')
5
6if HAS_FSPATH:
7    from pathlib import Path as str_to_path
8else:
9    str_to_path = None
10
11import unittest
12
13from clang.cindex import Cursor
14from clang.cindex import TranslationUnit
15
16def get_tu(source, lang='c', all_warnings=False, flags=[]):
17    """Obtain a translation unit from source and language.
18
19    By default, the translation unit is created from source file "t.<ext>"
20    where <ext> is the default file extension for the specified language. By
21    default it is C, so "t.c" is the default file name.
22
23    Supported languages are {c, cpp, objc}.
24
25    all_warnings is a convenience argument to enable all compiler warnings.
26    """
27    args = list(flags)
28    name = 't.c'
29    if lang == 'cpp':
30        name = 't.cpp'
31        args.append('-std=c++11')
32    elif lang == 'objc':
33        name = 't.m'
34    elif lang != 'c':
35        raise Exception('Unknown language: %s' % lang)
36
37    if all_warnings:
38        args += ['-Wall', '-Wextra']
39
40    return TranslationUnit.from_source(name, args, unsaved_files=[(name,
41                                       source)])
42
43def get_cursor(source, spelling):
44    """Obtain a cursor from a source object.
45
46    This provides a convenient search mechanism to find a cursor with specific
47    spelling within a source. The first argument can be either a
48    TranslationUnit or Cursor instance.
49
50    If the cursor is not found, None is returned.
51    """
52    # Convenience for calling on a TU.
53    root_cursor = source if isinstance(source, Cursor) else source.cursor
54
55    for cursor in root_cursor.walk_preorder():
56        if cursor.spelling == spelling:
57            return cursor
58
59    return None
60
61def get_cursors(source, spelling):
62    """Obtain all cursors from a source object with a specific spelling.
63
64    This provides a convenient search mechanism to find all cursors with
65    specific spelling within a source. The first argument can be either a
66    TranslationUnit or Cursor instance.
67
68    If no cursors are found, an empty list is returned.
69    """
70    # Convenience for calling on a TU.
71    root_cursor = source if isinstance(source, Cursor) else source.cursor
72
73    cursors = []
74    for cursor in root_cursor.walk_preorder():
75        if cursor.spelling == spelling:
76            cursors.append(cursor)
77
78    return cursors
79
80
81skip_if_no_fspath = unittest.skipUnless(HAS_FSPATH,
82                                        "Requires file system path protocol / Python 3.6+")
83
84__all__ = [
85    'get_cursor',
86    'get_cursors',
87    'get_tu',
88    'skip_if_no_fspath',
89    'str_to_path',
90]
91