Yet more CIndex API cleanup:

- Added more routines to manipulate/compare source locations and ranges
  - Switched clang_getCursor() over to take a CXSourceLocation rather
  than file/line/column.

llvm-svn: 94226
This commit is contained in:
Douglas Gregor 2010-01-22 21:44:22 +00:00
parent 00562558ab
commit 816fd36316
4 changed files with 137 additions and 21 deletions

View File

@ -493,6 +493,19 @@ CINDEX_LINKAGE const char *clang_getFileName(CXFile SFile);
*/ */
CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile); CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
/**
* \brief Retrieve a file handle within the given translation unit.
*
* \param tu the translation unit
*
* \param file_name the name of the file.
*
* \returns the file handle for the named file in the translation unit \p tu,
* or a NULL file handle if the file was not a part of this translation unit.
*/
CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
const char *file_name);
/** /**
* @} * @}
*/ */
@ -534,6 +547,38 @@ typedef struct {
unsigned end_int_data; unsigned end_int_data;
} CXSourceRange; } CXSourceRange;
/**
* \brief Retrieve a NULL (invalid) source location.
*/
CINDEX_LINKAGE CXSourceLocation clang_getNullLocation();
/**
* \determine Determine whether two source locations, which must refer into
* the same translation unit, refer to exactly the same point in the source
* code.
*
* \returns non-zero if the source locations refer to the same location, zero
* if they refer to different locations.
*/
CINDEX_LINKAGE unsigned clang_equalLocations(CXSourceLocation loc1,
CXSourceLocation loc2);
/**
* \brief Retrieves the source location associated with a given
* file/line/column in a particular translation unit.
*/
CINDEX_LINKAGE CXSourceLocation clang_getLocation(CXTranslationUnit tu,
CXFile file,
unsigned line,
unsigned column);
/**
* \brief Retrieve a source range given the beginning and ending source
* locations.
*/
CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin,
CXSourceLocation end);
/** /**
* \brief Retrieve the file, line, and column represented by the * \brief Retrieve the file, line, and column represented by the
* given source location. * given source location.
@ -574,13 +619,23 @@ CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range);
/* /*
* CXCursor Operations. * CXCursor Operations.
*/ */
/** /**
Usage: clang_getCursor() will translate a source/line/column position * \brief Map a source location to the cursor that describes the entity at that
into an AST cursor (to derive semantic information from the source code). * location in the source code.
*
* clang_getCursor() maps an arbitrary source location within a translation
* unit down to the most specific cursor that describes the entity at that
* location. For example, given an expression \c x + y, invoking
* clang_getCursor() with a source location pointing to "x" will return the
* cursor for "x"; similarly for "y". If the cursor points anywhere between
* "x" or "y" (e.g., on the + or the whitespace around it), clang_getCursor()
* will return a cursor referring to the "+" expression.
*
* \returns a cursor representing the entity at the given source location, or
* a NULL cursor if no such entity can be found.
*/ */
CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, CXSourceLocation);
const char *source_name,
unsigned line, unsigned column);
CINDEX_LINKAGE CXCursor clang_getNullCursor(void); CINDEX_LINKAGE CXCursor clang_getNullCursor(void);

View File

@ -134,6 +134,10 @@ static CXSourceRange translateSourceRange(ASTContext &Context, SourceRange R) {
return Result; return Result;
} }
static SourceLocation translateSourceLocation(CXSourceLocation L) {
return SourceLocation::getFromRawEncoding(L.int_data);
}
static SourceRange translateSourceRange(CXSourceRange R) { static SourceRange translateSourceRange(CXSourceRange R) {
return SourceRange(SourceLocation::getFromRawEncoding(R.begin_int_data), return SourceRange(SourceLocation::getFromRawEncoding(R.begin_int_data),
SourceLocation::getFromRawEncoding(R.end_int_data)); SourceLocation::getFromRawEncoding(R.end_int_data));
@ -996,6 +1000,42 @@ CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
// CXSourceLocation and CXSourceRange Operations. // CXSourceLocation and CXSourceRange Operations.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
extern "C" {
CXSourceLocation clang_getNullLocation() {
CXSourceLocation Result = { 0, 0 };
return Result;
}
unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
return loc1.ptr_data == loc2.ptr_data && loc1.int_data == loc2.int_data;
}
CXSourceLocation clang_getLocation(CXTranslationUnit tu,
CXFile file,
unsigned line,
unsigned column) {
if (!tu)
return clang_getNullLocation();
ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu);
SourceLocation SLoc
= CXXUnit->getSourceManager().getLocation(
static_cast<const FileEntry *>(file),
line, column);
return translateSourceLocation(CXXUnit->getASTContext(), SLoc, false);
}
CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
if (begin.ptr_data != end.ptr_data) {
CXSourceRange Result = { 0, 0, 0 };
return Result;
}
CXSourceRange Result = { begin.ptr_data, begin.int_data, end.int_data };
return Result;
}
void clang_getInstantiationLocation(CXSourceLocation location, void clang_getInstantiationLocation(CXSourceLocation location,
CXFile *file, CXFile *file,
unsigned *line, unsigned *line,
@ -1066,6 +1106,8 @@ CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
return Result; return Result;
} }
} // end: extern "C"
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// CXFile Operations. // CXFile Operations.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -1088,6 +1130,18 @@ time_t clang_getFileTime(CXFile SFile) {
FileEntry *FEnt = static_cast<FileEntry *>(SFile); FileEntry *FEnt = static_cast<FileEntry *>(SFile);
return FEnt->getModificationTime(); return FEnt->getModificationTime();
} }
CXFile clang_getFile(CXTranslationUnit tu, const char *file_name) {
if (!tu)
return 0;
ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu);
FileManager &FMgr = CXXUnit->getFileManager();
const FileEntry *File = FMgr.getFile(file_name, file_name+strlen(file_name));
return const_cast<FileEntry *>(File);
}
} // end: extern "C" } // end: extern "C"
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -1249,20 +1303,13 @@ enum CXChildVisitResult GetCursorVisitor(CXCursor cursor,
return CXChildVisit_Recurse; return CXChildVisit_Recurse;
} }
CXCursor clang_getCursor(CXTranslationUnit CTUnit, const char *source_name, CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
unsigned line, unsigned column) { if (!TU)
assert(CTUnit && "Passed null CXTranslationUnit");
ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
FileManager &FMgr = CXXUnit->getFileManager();
const FileEntry *File = FMgr.getFile(source_name,
source_name+strlen(source_name));
if (!File)
return clang_getNullCursor(); return clang_getNullCursor();
SourceLocation SLoc =
CXXUnit->getSourceManager().getLocation(File, line, column);
ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
SourceLocation SLoc = translateSourceLocation(Loc);
CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound); CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
if (SLoc.isValid()) { if (SLoc.isValid()) {
SourceRange RegionOfInterest(SLoc, SourceRange RegionOfInterest(SLoc,

View File

@ -7,6 +7,7 @@ _clang_disposeIndex
_clang_disposeString _clang_disposeString
_clang_disposeTranslationUnit _clang_disposeTranslationUnit
_clang_equalCursors _clang_equalCursors
_clang_equalLocations
_clang_getCString _clang_getCString
_clang_getCompletionChunkCompletionString _clang_getCompletionChunkCompletionString
_clang_getCompletionChunkKind _clang_getCompletionChunkKind
@ -21,11 +22,15 @@ _clang_getCursorReferenced
_clang_getCursorSpelling _clang_getCursorSpelling
_clang_getCursorUSR _clang_getCursorUSR
_clang_getDefinitionSpellingAndExtent _clang_getDefinitionSpellingAndExtent
_clang_getFile
_clang_getFileName _clang_getFileName
_clang_getFileTime _clang_getFileTime
_clang_getInstantiationLocation _clang_getInstantiationLocation
_clang_getLocation
_clang_getNullCursor _clang_getNullCursor
_clang_getNullLocation
_clang_getNumCompletionChunks _clang_getNumCompletionChunks
_clang_getRange
_clang_getRangeEnd _clang_getRangeEnd
_clang_getRangeStart _clang_getRangeStart
_clang_getTranslationUnitCursor _clang_getTranslationUnitCursor

View File

@ -161,7 +161,9 @@ static enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor,
clang_getInstantiationLocation(Loc, &file, 0, 0); clang_getInstantiationLocation(Loc, &file, 0, 0);
source = clang_getFileName(file); source = clang_getFileName(file);
if (source) { if (source) {
Ref = clang_getCursor(Data->TU, source, curLine, curColumn); CXSourceLocation RefLoc
= clang_getLocation(Data->TU, file, curLine, curColumn);
Ref = clang_getCursor(Data->TU, RefLoc);
if (Ref.kind == CXCursor_NoDeclFound) { if (Ref.kind == CXCursor_NoDeclFound) {
/* Nothing found here; that's fine. */ /* Nothing found here; that's fine. */
} else if (Ref.kind != CXCursor_FunctionDecl) { } else if (Ref.kind != CXCursor_FunctionDecl) {
@ -296,6 +298,7 @@ static int perform_file_scan(const char *ast_file, const char *source_file,
FILE *fp; FILE *fp;
unsigned line; unsigned line;
CXCursor prevCursor; CXCursor prevCursor;
CXFile file;
unsigned printed; unsigned printed;
unsigned start_line, start_col, last_line, last_col; unsigned start_line, start_col, last_line, last_col;
size_t i; size_t i;
@ -320,6 +323,7 @@ static int perform_file_scan(const char *ast_file, const char *source_file,
start_line = last_line = 1; start_line = last_line = 1;
start_col = last_col = 1; start_col = last_col = 1;
file = clang_getFile(TU, source_file);
while (!feof(fp)) { while (!feof(fp)) {
size_t len = 0; size_t len = 0;
int c; int c;
@ -334,7 +338,7 @@ static int perform_file_scan(const char *ast_file, const char *source_file,
for (i = 0; i < len ; ++i) { for (i = 0; i < len ; ++i) {
CXCursor cursor; CXCursor cursor;
cursor = clang_getCursor(TU, source_file, line, i+1); cursor = clang_getCursor(TU, clang_getLocation(TU, file, line, i+1));
if (!clang_equalCursors(cursor, prevCursor) && if (!clang_equalCursors(cursor, prevCursor) &&
prevCursor.kind != CXCursor_InvalidFile) { prevCursor.kind != CXCursor_InvalidFile) {
@ -656,8 +660,13 @@ int inspect_cursor_at(int argc, const char **argv) {
} }
for (Loc = 0; Loc < NumLocations; ++Loc) { for (Loc = 0; Loc < NumLocations; ++Loc) {
Cursor = clang_getCursor(TU, Locations[Loc].filename, CXFile file = clang_getFile(TU, Locations[Loc].filename);
Locations[Loc].line, Locations[Loc].column); if (!file)
continue;
Cursor = clang_getCursor(TU,
clang_getLocation(TU, file, Locations[Loc].line,
Locations[Loc].column));
PrintCursor(Cursor); PrintCursor(Cursor);
printf("\n"); printf("\n");
free(Locations[Loc].filename); free(Locations[Loc].filename);