зеркало из https://github.com/microsoft/clang-1.git
cindex/Python: Add TranslationUnit.get_includes, patch by Andrew Sutton!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96106 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
b51abe9b5f
Коммит
ef7f798c09
|
@ -719,6 +719,25 @@ class TranslationUnit(ClangObject):
|
|||
"""Get the original translation unit source file name."""
|
||||
return TranslationUnit_spelling(self)
|
||||
|
||||
def get_includes(self):
|
||||
"""
|
||||
Return an iterable sequence of FileInclusion objects that describe the
|
||||
sequence of inclusions in a translation unit. The first object in
|
||||
this sequence is always the input file. Note that this method will not
|
||||
recursively iterate over header files included through precompiled
|
||||
headers.
|
||||
"""
|
||||
def visitor(fobj, lptr, depth, includes):
|
||||
loc = lptr.contents
|
||||
includes.append(FileInclusion(loc.file, File(fobj), loc, depth))
|
||||
|
||||
# Automatically adapt CIndex/ctype pointers to python objects
|
||||
includes = []
|
||||
TranslationUnit_includes(self,
|
||||
TranslationUnit_includes_callback(visitor),
|
||||
includes)
|
||||
return iter(includes)
|
||||
|
||||
class File(ClangObject):
|
||||
"""
|
||||
The File class represents a particular source file that is part of a
|
||||
|
@ -735,6 +754,26 @@ class File(ClangObject):
|
|||
"""Return the last modification time of the file."""
|
||||
return File_time(self)
|
||||
|
||||
class FileInclusion(object):
|
||||
"""
|
||||
The FileInclusion class represents the inclusion of one source file by
|
||||
another via a '#include' directive or as the input file for the translation
|
||||
unit. This class provides information about the included file, the including
|
||||
file, the location of the '#include' directive and the depth of the included
|
||||
file in the stack. Note that the input file has depth 0.
|
||||
"""
|
||||
|
||||
def __init__(self, src, tgt, loc, depth):
|
||||
self.source = src
|
||||
self.include = tgt
|
||||
self.location = loc
|
||||
self.depth = depth
|
||||
|
||||
@property
|
||||
def is_input_file(self):
|
||||
"""True if the included file is the input file."""
|
||||
return self.depth == 0
|
||||
|
||||
# Additional Functions and Types
|
||||
|
||||
# String Functions
|
||||
|
@ -870,6 +909,15 @@ TranslationUnit_spelling.errcheck = _CXString.from_result
|
|||
TranslationUnit_dispose = lib.clang_disposeTranslationUnit
|
||||
TranslationUnit_dispose.argtypes = [TranslationUnit]
|
||||
|
||||
TranslationUnit_includes_callback = CFUNCTYPE(None,
|
||||
c_object_p,
|
||||
POINTER(SourceLocation),
|
||||
c_uint, py_object)
|
||||
TranslationUnit_includes = lib.clang_getInclusions
|
||||
TranslationUnit_includes.argtypes = [TranslationUnit,
|
||||
TranslationUnit_includes_callback,
|
||||
py_object]
|
||||
|
||||
# File Functions
|
||||
File_name = lib.clang_getFileName
|
||||
File_name.argtypes = [File]
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
#===- cindex-includes.py - cindex/Python Inclusion Graph -----*- python -*--===#
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===------------------------------------------------------------------------===#
|
||||
|
||||
"""
|
||||
A simple command line tool for dumping a Graphviz description (dot) that
|
||||
describes include dependencies.
|
||||
"""
|
||||
|
||||
def main():
|
||||
import sys
|
||||
from clang.cindex import Index
|
||||
|
||||
# FIXME: Allow the user to pass command line options to clang so that
|
||||
# we can use -D and -U.
|
||||
from optparse import OptionParser, OptionGroup
|
||||
|
||||
parser = OptionParser("usage: %prog [options] {filename} [clang-args*]")
|
||||
parser.disable_interspersed_args()
|
||||
(opts, args) = parser.parse_args()
|
||||
if len(args) == 0:
|
||||
parser.error('invalid number arguments')
|
||||
|
||||
# FIXME: Add an output file option
|
||||
out = sys.stdout
|
||||
|
||||
input_path = args.pop(0)
|
||||
|
||||
|
||||
index = Index.create()
|
||||
tu = index.parse(input_path, args)
|
||||
if not tu:
|
||||
parser.error("unable to load input")
|
||||
|
||||
# A helper function for generating the node name.
|
||||
def name(f):
|
||||
return "\"" + f.name + "\""
|
||||
|
||||
# Generate the include graph
|
||||
out.write("digraph G {\n")
|
||||
for i in tu.get_includes():
|
||||
line = " ";
|
||||
if i.is_input_file:
|
||||
# Always write the input file as a node just in case it doesn't
|
||||
# actually include anything. This would generate a 1 node graph.
|
||||
line += name(i.include)
|
||||
else:
|
||||
line += name(i.source) + "->" + name(i.include)
|
||||
line += "\n";
|
||||
out.write(line)
|
||||
out.write("}\n")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef HEADER1
|
||||
#define HEADER1
|
||||
|
||||
#include "header3.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef HEADER2
|
||||
#define HEADER2
|
||||
|
||||
#include "header3.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,3 @@
|
|||
// Not a guarded header!
|
||||
|
||||
void f();
|
|
@ -0,0 +1,5 @@
|
|||
#include "header1.h"
|
||||
#include "header2.h"
|
||||
#include "header1.h"
|
||||
|
||||
int main() { }
|
|
@ -49,3 +49,25 @@ def test_unsaved_files_2():
|
|||
('fake.c', StringIO.StringIO('int x;'))])
|
||||
spellings = [c.spelling for c in tu.cursor.get_children()]
|
||||
assert spellings[-1] == 'x'
|
||||
|
||||
|
||||
def test_includes():
|
||||
def eq(expected, actual):
|
||||
if not actual.is_input_file:
|
||||
return expected[0] == actual.source.name and \
|
||||
expected[1] == actual.include.name
|
||||
else:
|
||||
return expected[1] == actual.include.name
|
||||
|
||||
src = os.path.join(kInputsDir, 'include.cpp')
|
||||
h1 = os.path.join(kInputsDir, "header1.h")
|
||||
h2 = os.path.join(kInputsDir, "header2.h")
|
||||
h3 = os.path.join(kInputsDir, "header3.h")
|
||||
inc = [(None, src), (src, h1), (h1, h3), (src, h2), (h2, h3)]
|
||||
|
||||
index = Index.create()
|
||||
tu = index.parse(src)
|
||||
for i in zip(inc, tu.get_includes()):
|
||||
assert eq(i[0], i[1])
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче