diff options
author | Ted Kremenek <kremenek@apple.com> | 2010-03-13 02:50:34 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2010-03-13 02:50:34 +0000 |
commit | 896b70ffc348f6e2c680b5fb5841984d5785b7b5 (patch) | |
tree | 8e7c669be5f0d81236f4d52de0766d584723e8d1 | |
parent | 1c471f3e1c0ec8cbc82447bb35908dfc55463e46 (diff) |
Implement several CIndex functions for constructing USRs from C-strings instead of AST elements.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98421 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang-c/Index.h | 115 | ||||
-rw-r--r-- | tools/CIndex/CIndex.exports | 6 | ||||
-rw-r--r-- | tools/CIndex/CIndexUSRs.cpp | 198 |
3 files changed, 244 insertions, 75 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index da186f6424..ff7dd103e8 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -171,7 +171,7 @@ CINDEX_LINKAGE void clang_disposeString(CXString string); */ CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH, int displayDiagnostics); - + /** * \brief Destroy the given index. * @@ -297,7 +297,7 @@ CINDEX_LINKAGE CXSourceLocation clang_getLocation(CXTranslationUnit tu, * \brief Retrieve a NULL (invalid) source range. */ CINDEX_LINKAGE CXSourceRange clang_getNullRange(); - + /** * \brief Retrieve a source range given the beginning and ending source * locations. @@ -357,11 +357,11 @@ CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range); */ enum CXDiagnosticSeverity { /** - * \brief A diagnostic that has been suppressed, e.g., by a command-line + * \brief A diagnostic that has been suppressed, e.g., by a command-line * option. */ CXDiagnostic_Ignored = 0, - + /** * \brief This diagnostic is a note that should be attached to the * previous (non-note) diagnostic. @@ -451,7 +451,7 @@ enum CXDiagnosticDisplayOptions { * diagnostic, also include information about source ranges in a * machine-parsable format. * - * This option corresponds to the clang flag + * This option corresponds to the clang flag * \c -fdiagnostics-print-source-range-info. */ CXDiagnostic_DisplaySourceRanges = 0x04 @@ -461,13 +461,13 @@ enum CXDiagnosticDisplayOptions { * \brief Format the given diagnostic in a manner that is suitable for display. * * This routine will format the given diagnostic to a string, rendering - * the diagnostic according to the various options given. The - * \c clang_defaultDiagnosticDisplayOptions() function returns the set of + * the diagnostic according to the various options given. The + * \c clang_defaultDiagnosticDisplayOptions() function returns the set of * options that most closely mimics the behavior of the clang compiler. * * \param Diagnostic The diagnostic to print. * - * \param Options A set of options that control the diagnostic display, + * \param Options A set of options that control the diagnostic display, * created by combining \c CXDiagnosticDisplayOptions values. * * \returns A new string containing for formatted diagnostic. @@ -491,7 +491,7 @@ CINDEX_LINKAGE unsigned clang_defaultDiagnosticDisplayOptions(void); /** * \brief Determine the severity of the given diagnostic. */ -CINDEX_LINKAGE enum CXDiagnosticSeverity +CINDEX_LINKAGE enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic); /** @@ -512,21 +512,21 @@ CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic); * diagnostic. */ CINDEX_LINKAGE unsigned clang_getDiagnosticNumRanges(CXDiagnostic); - + /** * \brief Retrieve a source range associated with the diagnostic. * * A diagnostic's source ranges highlight important elements in the source * code. On the command line, Clang displays source ranges by - * underlining them with '~' characters. + * underlining them with '~' characters. * * \param Diagnostic the diagnostic whose range is being extracted. * - * \param Range the zero-based index specifying which range to + * \param Range the zero-based index specifying which range to * * \returns the requested source range. */ -CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic, +CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic, unsigned Range); /** @@ -560,7 +560,7 @@ CINDEX_LINKAGE unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic); * \returns A string containing text that should be replace the source * code indicated by the \c ReplacementRange. */ -CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, +CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, unsigned FixIt, CXSourceRange *ReplacementRange); @@ -577,7 +577,7 @@ CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, * * @{ */ - + /** * \brief Get the original translation unit source file name. */ @@ -625,22 +625,22 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile( const char **clang_command_line_args, unsigned num_unsaved_files, struct CXUnsavedFile *unsaved_files); - + /** * \brief Create a translation unit from an AST file (-emit-ast). */ -CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex, +CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex, const char *ast_filename); /** * \brief Destroy the specified CXTranslationUnit object. */ CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit); - + /** * @} */ - + /** * \brief Describes the kind of entity that a cursor refers to. */ @@ -1083,6 +1083,47 @@ CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent, CINDEX_LINKAGE CXString clang_getCursorUSR(CXCursor); /** + * \brief Construct a USR for a specified Objective-C class. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCClass(const char *class_name); + +/** + * \brief Construct a USR for a specified Objective-C category. + */ +CINDEX_LINKAGE CXString + clang_constructUSR_ObjCategory(const char *class_name, + const char *category_name); + +/** + * \brief Construct a USR for a specified Objective-C protocol. + */ +CINDEX_LINKAGE CXString + clang_constructUSR_ObjCProtocol(const char *protocol_name); + + +/** + * \brief Construct a USR for a specified Objective-C instance variable and + * the USR for its containing class. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCIvar(const char *name, + CXString classUSR); + +/** + * \brief Construct a USR for a specified Objective-C method and + * the USR for its containing class. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCMethod(const char *name, + unsigned isInstanceMethod, + CXString classUSR); + +/** + * \brief Construct a USR for a specified Objective-C property and the USR + * for its containing class. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCProperty(const char *property, + CXString classUSR); + +/** * \brief Retrieve a name for the entity referenced by this cursor. */ CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor); @@ -1157,22 +1198,22 @@ typedef enum CXTokenKind { * \brief A token that contains some kind of punctuation. */ CXToken_Punctuation, - + /** * \brief A language keyword. */ CXToken_Keyword, - + /** * \brief An identifier (that is not a keyword). */ CXToken_Identifier, - + /** * \brief A numeric, string, or character literal. */ CXToken_Literal, - + /** * \brief A comment. */ @@ -1191,7 +1232,7 @@ typedef struct { * \brief Determine the kind of the given token. */ CINDEX_LINKAGE CXTokenKind clang_getTokenKind(CXToken); - + /** * \brief Determine the spelling of the given token. * @@ -1199,13 +1240,13 @@ CINDEX_LINKAGE CXTokenKind clang_getTokenKind(CXToken); * the text of an identifier or keyword. */ CINDEX_LINKAGE CXString clang_getTokenSpelling(CXTranslationUnit, CXToken); - + /** * \brief Retrieve the source location of the given token. */ -CINDEX_LINKAGE CXSourceLocation clang_getTokenLocation(CXTranslationUnit, +CINDEX_LINKAGE CXSourceLocation clang_getTokenLocation(CXTranslationUnit, CXToken); - + /** * \brief Retrieve a source range that covers the given token. */ @@ -1230,7 +1271,7 @@ CINDEX_LINKAGE CXSourceRange clang_getTokenExtent(CXTranslationUnit, CXToken); */ CINDEX_LINKAGE void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, CXToken **Tokens, unsigned *NumTokens); - + /** * \brief Annotate the given set of tokens by providing cursors for each token * that can be mapped to a specific entity within the abstract syntax tree. @@ -1264,17 +1305,17 @@ CINDEX_LINKAGE void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, CINDEX_LINKAGE void clang_annotateTokens(CXTranslationUnit TU, CXToken *Tokens, unsigned NumTokens, CXCursor *Cursors); - + /** * \brief Free the given set of tokens. */ -CINDEX_LINKAGE void clang_disposeTokens(CXTranslationUnit TU, +CINDEX_LINKAGE void clang_disposeTokens(CXTranslationUnit TU, CXToken *Tokens, unsigned NumTokens); - + /** * @} */ - + /** * \defgroup CINDEX_DEBUG Debugging facilities * @@ -1689,7 +1730,7 @@ void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results); * \brief Determine the number of diagnostics produced prior to the * location where code completion was performed. */ -CINDEX_LINKAGE +CINDEX_LINKAGE unsigned clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *Results); /** @@ -1701,7 +1742,7 @@ unsigned clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *Results); * \returns the requested diagnostic. This diagnostic must be freed * via a call to \c clang_disposeDiagnostic(). */ -CINDEX_LINKAGE +CINDEX_LINKAGE CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results, unsigned Index); @@ -1726,10 +1767,10 @@ CINDEX_LINKAGE CXString clang_getClangVersion(); * \brief Return a version string, suitable for showing to a user, but not * intended to be parsed (the format is not guaranteed to be stable). */ - - + + /** - * \brief Visitor invoked for each file in a translation unit + * \brief Visitor invoked for each file in a translation unit * (used with clang_getInclusions()). * * This visitor function will be invoked by clang_getInclusions() for each diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports index 5b9530052b..a73114caf5 100644 --- a/tools/CIndex/CIndex.exports +++ b/tools/CIndex/CIndex.exports @@ -2,6 +2,12 @@ _clang_annotateTokens _clang_codeComplete _clang_codeCompleteGetDiagnostic _clang_codeCompleteGetNumDiagnostics +_clang_constructUSR_ObjCClass +_clang_constructUSR_ObjCategory +_clang_constructUSR_ObjCIvar +_clang_constructUSR_ObjCMethod +_clang_constructUSR_ObjCProtocol +_clang_constructUSR_ObjCProperty _clang_createIndex _clang_createTranslationUnit _clang_createTranslationUnitFromSourceFile diff --git a/tools/CIndex/CIndexUSRs.cpp b/tools/CIndex/CIndexUSRs.cpp index 922f4b3fa7..234c03cc3e 100644 --- a/tools/CIndex/CIndexUSRs.cpp +++ b/tools/CIndex/CIndexUSRs.cpp @@ -29,23 +29,77 @@ class USRGenerator : public DeclVisitor<USRGenerator> { bool IgnoreResults; public: USRGenerator(llvm::raw_ostream &out) : Out(out), IgnoreResults(false) {} - + bool ignoreResults() const { return IgnoreResults; } - + + // Visitation methods from generating USRs from AST elements. void VisitBlockDecl(BlockDecl *D); void VisitDeclContext(DeclContext *D); void VisitFieldDecl(FieldDecl *D); void VisitFunctionDecl(FunctionDecl *D); void VisitNamedDecl(NamedDecl *D); void VisitNamespaceDecl(NamespaceDecl *D); - void VisitObjCContainerDecl(ObjCContainerDecl *CD); + void VisitObjCContainerDecl(ObjCContainerDecl *CD); void VisitObjCMethodDecl(ObjCMethodDecl *MD); void VisitObjCPropertyDecl(ObjCPropertyDecl *D); void VisitTagDecl(TagDecl *D); void VisitTypedefDecl(TypedefDecl *D); + + + /// String generation methods used both by the visitation methods + /// and from other clients that want to directly generate USRs. These + /// methods do not construct complete USRs (which incorporate the parents + /// of an AST element), but only the fragments concerning the AST element + /// itself. + + /// Generate a USR fragment for a named declaration. This does + /// not include the USR component for the parent. + void GenNamedDecl(llvm::StringRef name); + + /// Generate a USR for an Objective-C class. + void GenObjCClass(llvm::StringRef cls); + /// Generate a USR for an Objective-C class category. + void GenObjCCategory(llvm::StringRef cls, llvm::StringRef cat); + /// Generate a USR fragment for an Objective-C instance variable. The + /// complete USR can be created by concatenating the USR for the + /// encompassing class with this USR fragment. + void GenObjCIvar(llvm::StringRef ivar); + /// Generate a USR fragment for an Objective-C method. + void GenObjCMethod(llvm::StringRef sel, bool isInstanceMethod); + /// Generate a USR fragment for an Objective-C property. + void GenObjCProperty(llvm::StringRef prop); + /// Generate a USR for an Objective-C protocol. + void GenObjCProtocol(llvm::StringRef prot); +}; + +class StringUSRGenerator { +private: + llvm::SmallString<1024> StrBuf; + llvm::raw_svector_ostream Out; + USRGenerator UG; +public: + StringUSRGenerator() + : Out(StrBuf), UG(Out) {} + + llvm::StringRef str() { + return Out.str(); + } + + USRGenerator* operator->() { return &UG; } + + template <typename T> + llvm::raw_svector_ostream &operator<<(const T &x) { + Out << x; + return Out; + } }; + } // end anonymous namespace +//===----------------------------------------------------------------------===// +// Generating USRs from ASTS. +//===----------------------------------------------------------------------===// + void USRGenerator::VisitBlockDecl(BlockDecl *D) { VisitDeclContext(D->getDeclContext()); // FIXME: Better support for anonymous blocks. @@ -76,8 +130,8 @@ void USRGenerator::VisitFunctionDecl(FunctionDecl *D) { void USRGenerator::VisitNamedDecl(NamedDecl *D) { VisitDeclContext(D->getDeclContext()); const std::string &s = D->getNameAsString(); -// assert(!s.empty()); - Out << "@^" << s; + // assert(!s.empty()); + GenNamedDecl(s); } void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) { @@ -87,8 +141,8 @@ void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) { void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) { Visit(cast<Decl>(D->getDeclContext())); - Out << (D->isInstanceMethod() ? "(im)" : "(cm)"); - Out << DeclarationName(D->getSelector()).getAsString(); + GenObjCMethod(DeclarationName(D->getSelector()).getAsString(), + D->isInstanceMethod()); } void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) { @@ -97,29 +151,29 @@ void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) { assert(false && "Invalid ObjC container."); case Decl::ObjCInterface: case Decl::ObjCImplementation: - Out << "objc(cs)" << D->getName(); + GenObjCClass(D->getName()); break; case Decl::ObjCCategory: { ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); - Out << "objc(cy)" << CD->getClassInterface()->getName() - << '^' << CD->getName(); + GenObjCCategory(CD->getClassInterface()->getName(), + CD->getName()); break; } case Decl::ObjCCategoryImpl: { ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); - Out << "objc(cy)" << CD->getClassInterface()->getName() - << '^' << CD->getName(); + GenObjCCategory(CD->getClassInterface()->getName(), + CD->getName()); break; } case Decl::ObjCProtocol: - Out << "objc(pl)" << cast<ObjCProtocolDecl>(D)->getName(); + GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName()); break; } } void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { Visit(cast<Decl>(D->getDeclContext())); - Out << "(py)" << D->getName(); + GenObjCProperty(D->getName()); } void USRGenerator::VisitTagDecl(TagDecl *D) { @@ -130,12 +184,12 @@ void USRGenerator::VisitTagDecl(TagDecl *D) { case TagDecl::TK_union: Out << "@U^"; break; case TagDecl::TK_enum: Out << "@E^"; break; } - + // FIXME: Better support for anonymous structures and enums. const std::string &s = D->getNameAsString(); if (s.empty()) { if (TypedefDecl *TD = D->getTypedefForAnonDecl()) - Out << "^anontd^" << TD->getNameAsString(); + Out << "^anontd^" << TD->getNameAsString(); else Out << "^anon"; } @@ -146,36 +200,104 @@ void USRGenerator::VisitTagDecl(TagDecl *D) { void USRGenerator::VisitTypedefDecl(TypedefDecl *D) { DeclContext *DC = D->getDeclContext(); if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC)) - Visit(DCN); + Visit(DCN); Out << "typedef@" << D->getName(); } -// FIXME: This is a skeleton implementation. It will be overhauled. -static CXString ConstructUSR(Decl *D) { - llvm::SmallString<1024> StrBuf; - { - llvm::raw_svector_ostream Out(StrBuf); - USRGenerator UG(Out); - UG.Visit(static_cast<Decl*>(D)); - if (UG.ignoreResults()) - return createCXString(NULL); - } - - if (StrBuf.empty()) - return createCXString(NULL); - - // Return a copy of the string that must be disposed by the caller. - return createCXString(StrBuf.str(), true); -} +//===----------------------------------------------------------------------===// +// General purpose USR generation methods. +//===----------------------------------------------------------------------===// + +void USRGenerator::GenNamedDecl(llvm::StringRef name) { + Out << "@^" << name; +} + +void USRGenerator::GenObjCClass(llvm::StringRef cls) { + Out << "objc(cs)" << cls; +} +void USRGenerator::GenObjCCategory(llvm::StringRef cls, llvm::StringRef cat) { + Out << "objc(cy)" << cls << '^' << cat; +} + +void USRGenerator::GenObjCIvar(llvm::StringRef ivar) { + GenNamedDecl(ivar); +} + +void USRGenerator::GenObjCMethod(llvm::StringRef meth, bool isInstanceMethod) { + Out << (isInstanceMethod ? "(im)" : "(cm)") << meth; +} + +void USRGenerator::GenObjCProperty(llvm::StringRef prop) { + Out << "(py)" << prop; +} + +void USRGenerator::GenObjCProtocol(llvm::StringRef prot) { + Out << "objc(pl)" << prot; +} + +//===----------------------------------------------------------------------===// +// API hooks. +//===----------------------------------------------------------------------===// extern "C" { CXString clang_getCursorUSR(CXCursor C) { - if (Decl *D = cxcursor::getCursorDecl(C)) - return ConstructUSR(D); - - return createCXString(NULL); + Decl *D = cxcursor::getCursorDecl(C); + if (!D) + return createCXString(NULL); + + StringUSRGenerator SUG; + SUG->Visit(static_cast<Decl*>(D)); + + if (SUG->ignoreResults() || SUG.str().empty()) + return createCXString(NULL); + + // Return a copy of the string that must be disposed by the caller. + return createCXString(SUG.str(), true); +} + +CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) { + StringUSRGenerator SUG; + SUG << clang_getCString(classUSR); + SUG->GenObjCIvar(name); + return createCXString(SUG.str(), true); +} + +CXString clang_constructUSR_ObjCMethod(const char *name, + unsigned isInstanceMethod, + CXString classUSR) { + StringUSRGenerator SUG; + SUG << clang_getCString(classUSR); + SUG->GenObjCMethod(name, isInstanceMethod); + return createCXString(SUG.str(), true); +} + +CXString clang_constructUSR_ObjCClass(const char *name) { + StringUSRGenerator SUG; + SUG->GenObjCClass(name); + return createCXString(SUG.str(), true); +} + +CXString clang_constructUSR_ObjCProtocol(const char *name) { + StringUSRGenerator SUG; + SUG->GenObjCProtocol(name); + return createCXString(SUG.str(), true); +} + +CXString clang_constructUSR_ObjCategory(const char *class_name, + const char *category_name) { + StringUSRGenerator SUG; + SUG->GenObjCCategory(class_name, category_name); + return createCXString(SUG.str(), true); +} + +CXString clang_constructUSR_ObjCProperty(const char *property, + CXString classUSR) { + StringUSRGenerator SUG; + SUG << clang_getCString(classUSR); + SUG->GenObjCProperty(property); + return createCXString(SUG.str(), true); } } // end extern "C" |