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