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