Commit 1f251395 authored by ussrhero's avatar ussrhero

type enum for clang

parent 2616b468
......@@ -150,6 +150,9 @@ protected:
///////////////////////////////////////////////////////////////////////////////
class TypeInfoEnumerator;
typedef boost::shared_ptr<TypeInfoEnumerator> TypeInfoEnumeratorPtr;
class TypeInfoProvider;
typedef boost::shared_ptr<TypeInfoProvider> TypeInfoProviderPtr;
......@@ -158,7 +161,12 @@ class TypeInfoProvider
public:
virtual TypeInfoPtr getTypeByName(const std::wstring& name) = 0;
virtual TypeInfoEnumeratorPtr getTypeEnumerator(const std::wstring& mask = L"") = 0;
};
class TypeInfoEnumerator {
public:
virtual TypeInfoPtr Next() = 0;
};
TypeInfoProviderPtr getTypeInfoProviderFromSource( const std::wstring& source, const std::wstring& opts = L"" );
......
......@@ -17,6 +17,7 @@
#include "strconvert.h"
#include "clang.h"
#include "fnmatch.h"
using namespace clang;
using namespace clang::tooling;
......@@ -211,8 +212,8 @@ TypeInfoClangStruct::TypeInfoClangStruct(const std::wstring & name, ClangASTSess
m_astSession(session),
m_decl(decl)
{
if ( decl->isInvalidDecl() )
throw TypeException(L"Invalid declaration");
// if ( decl->isInvalidDecl() )
/// throw TypeException(L"Invalid declaration");
}
///////////////////////////////////////////////////////////////////////////////
......@@ -389,17 +390,20 @@ void TypeInfoClangEnum::getFields()
///////////////////////////////////////////////////////////////////////////////
class StructDefVisitor : public RecursiveASTVisitor<StructDefVisitor>
class DeclNamedVisitor : public RecursiveASTVisitor<DeclNamedVisitor>
{
public:
StructDefVisitor(ClangASTSessionPtr& astSession, const std::string& typeName) :
DeclNamedVisitor(ClangASTSessionPtr& astSession, const std::string& typeName) :
m_session(astSession),
m_typeName(typeName)
{}
bool VisitCXXRecordDecl(CXXRecordDecl *Declaration)
{
if ( Declaration->isInvalidDecl() )
return true;
std::string& name = Declaration->getQualifiedNameAsString();
if ( name != m_typeName)
......@@ -415,6 +419,9 @@ public:
bool VisitTypedefDecl(TypedefDecl *Declaration)
{
if ( Declaration->isInvalidDecl() )
return true;
std::string& name = Declaration->getQualifiedNameAsString();
if ( name != m_typeName)
......@@ -429,15 +436,24 @@ public:
bool VisitFunctionDecl(FunctionDecl *Declaration)
{
if ( Declaration->isInvalidDecl() )
return true;
if ( Declaration->getTemplatedKind() == FunctionDecl::TemplatedKind:: TK_FunctionTemplate )
return true;
if ( CXXRecordDecl *parentClassDecl = llvm::dyn_cast<CXXRecordDecl>(Declaration->getDeclContext()))
{
if ( parentClassDecl->getDescribedClassTemplate() )
return true;
}
std::string& name = Declaration->getQualifiedNameAsString();
if ( name != m_typeName)
return true;
if ( Declaration->isInvalidDecl() )
throw TypeException(L"Invalid declaration");
const FunctionProtoType* protoType = Declaration->getFunctionType()->getAs<FunctionProtoType>();
const FunctionProtoType* protoType = Declaration->getFunctionType()->getAs<FunctionProtoType>();
m_typeInfo = TypeInfoPtr( new TypeInfoClangFunc(m_session, protoType ) );
......@@ -446,6 +462,9 @@ public:
bool VisitEnumDecl (EnumDecl *Declaration)
{
if ( Declaration->isInvalidDecl() )
return true;
std::string& name = Declaration->getQualifiedNameAsString();
if ( name != m_typeName)
......@@ -471,9 +490,144 @@ private:
///////////////////////////////////////////////////////////////////////////////
class DeclNextVisitor : public RecursiveASTVisitor<DeclNextVisitor>
{
public:
DeclNextVisitor(ClangASTSessionPtr& astSession, const std::string& mask, size_t pos) :
m_session(astSession),
m_mask(mask),
m_currentPos(0),
m_startPos(pos)
{}
bool VisitCXXRecordDecl(CXXRecordDecl *Declaration)
{
try {
if (m_startPos > m_currentPos++ )
return true;
if ( Declaration->isInvalidDecl() )
return true;
CXXRecordDecl * definition = Declaration->getDefinition();
if ( definition && definition->isInvalidDecl() )
return true;
std::string name = Declaration->getNameAsString();
if (m_mask.length() > 0 && !fnmatch(m_mask, name) )
return true;
TypeInfoPtr typeInfo;
if ( definition )
typeInfo = TypeInfoPtr( new TypeInfoClangStruct( strToWStr(name), m_session, definition ) );
else
typeInfo = TypeInfoPtr( new TypeInfoClangStructNoDef( strToWStr(name), m_session, Declaration ) );
m_typeInfo = typeInfo;
return false;
} catch(TypeException& )
{}
return true;
}
bool VisitFunctionDecl(FunctionDecl *Declaration)
{
try {
if (m_startPos > m_currentPos++ )
return true;
if ( Declaration->isInvalidDecl() )
return true;
if ( Declaration->getTemplatedKind() == FunctionDecl::TemplatedKind:: TK_FunctionTemplate )
return true;
if ( CXXRecordDecl *parentClassDecl = llvm::dyn_cast<CXXRecordDecl>(Declaration->getDeclContext()))
{
if ( parentClassDecl->getDescribedClassTemplate() )
return true;
}
std::string name = Declaration->getNameAsString();
if (m_mask.length() > 0 && !fnmatch(m_mask, name) )
return true;
const FunctionProtoType* protoType = Declaration->getFunctionType()->getAs<FunctionProtoType>();
TypeInfoPtr typeInfo = TypeInfoPtr( new TypeInfoClangFunc(m_session, protoType ) );
m_typeInfo = typeInfo;
return false;
} catch(TypeException& )
{}
return true;
}
bool VisitEnumDecl (EnumDecl *Declaration)
{
try {
if (m_startPos > m_currentPos++ )
return true;
if ( Declaration->isInvalidDecl() )
return true;
std::string name = Declaration->getNameAsString();
if (m_mask.length() > 0 && !fnmatch(m_mask, name) )
return true;
TypeInfoPtr typeInfo = TypeInfoPtr( new TypeInfoClangEnum(m_session, Declaration) );
m_typeInfo = typeInfo;
return false;
} catch(TypeException& )
{}
return true;
}
TypeInfoPtr getTypeInfo() {
return m_typeInfo;
}
size_t currentPos() {
return m_currentPos;
}
private:
std::string m_mask;
ClangASTSessionPtr m_session;
TypeInfoPtr m_typeInfo;
size_t m_currentPos;
size_t m_startPos;
};
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr ClangASTSession::getTypeInfo(const std::wstring& name)
{
StructDefVisitor visitor( shared_from_this(), wstrToStr(name) );
DeclNamedVisitor visitor( shared_from_this(), wstrToStr(name) );
visitor.TraverseDecl( m_astUnit->getASTContext().getTranslationUnitDecl() );
TypeInfoPtr ptr = visitor.getTypeInfo();
......@@ -542,6 +696,14 @@ TypeInfoPtr TypeInfoProviderClang::getTypeByName(const std::wstring& name)
return m_astSession->getTypeInfo(name);
}
///////////////////////////////////////////////////////////////////////////////
TypeInfoEnumeratorPtr TypeInfoProviderClang::getTypeEnumerator(const std::wstring& mask)
{
return TypeInfoEnumeratorPtr( new TypeInfoProviderClangEnum(mask, m_astSession) );
}
///////////////////////////////////////////////////////////////////////////////
TypeInfoProviderPtr getTypeInfoProviderFromSource( const std::wstring& source, const std::wstring& opts )
......@@ -551,6 +713,15 @@ TypeInfoProviderPtr getTypeInfoProviderFromSource( const std::wstring& source,
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr TypeInfoProviderClangEnum::Next()
{
DeclNextVisitor visitor( m_astSession, m_mask, m_pos);
visitor.TraverseDecl( m_astSession->getASTContext().getTranslationUnitDecl() );
m_pos = visitor.currentPos();
return visitor.getTypeInfo();
}
///////////////////////////////////////////////////////////////////////////////
}
......@@ -304,6 +304,26 @@ protected:
};
class TypeInfoProviderClangEnum : public TypeInfoEnumerator{
public:
virtual TypeInfoPtr Next();
TypeInfoProviderClangEnum(const std::wstring& mask, ClangASTSessionPtr ast) :
m_mask(wstrToStr(mask)),
m_astSession(ast),
m_pos(0)
{}
private:
std::string m_mask;
ClangASTSessionPtr m_astSession;
size_t m_pos;
};
class TypeInfoProviderClang : public TypeInfoProvider
{
public:
......@@ -314,6 +334,8 @@ private:
virtual TypeInfoPtr getTypeByName(const std::wstring& name);
virtual TypeInfoEnumeratorPtr getTypeEnumerator(const std::wstring& mask);
private:
ClangASTSessionPtr m_astSession;
......@@ -322,4 +344,4 @@ private:
}
\ No newline at end of file
}
#include "stdafx.h"
#include <boost/regex.hpp>
/////////////////////////////////////////////////////////////////////////////////
namespace kdlib {
const boost::regex r1("\\?");
const boost::regex r2("\\*");
const boost::regex r3("\\.");
bool fnmatch( const std::string& pattern, const std::string& str)
{
std::string mask = pattern;
mask = boost::regex_replace(mask, r1, ".");
mask = boost::regex_replace(mask, r2, ".*");
mask = boost::regex_replace(mask, r3, "\\.");
boost::smatch matchResult;
boost::regex regEx(mask);
return boost::regex_match(str, matchResult, regEx);
}
const boost::wregex wr1(L"\\?");
const boost::wregex wr2(L"\\*");
const boost::wregex wr3(L"\\.");
bool fnmatch( const std::wstring& pattern, const std::wstring& str)
{
std::wstring mask = pattern;
mask = boost::regex_replace(mask, wr1, L".");
mask = boost::regex_replace(mask, wr2, L".*");
mask = boost::regex_replace(mask, wr3, L"\\.");
boost::wsmatch matchResult;
boost::wregex regEx(mask);
return boost::regex_match(str, matchResult, regEx);
}
}
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <string>
namespace kdlib {
///////////////////////////////////////////////////////////////////////////////
bool fnmatch( const std::string& pattern, const std::string& str);
bool fnmatch( const std::wstring& pattern, const std::wstring& str);
///////////////////////////////////////////////////////////////////////////////
}
......@@ -44,6 +44,7 @@
<ClCompile Include="dia\diawrapper.cpp" />
<ClCompile Include="dia\symexport.cpp" />
<ClCompile Include="disasm.cpp" />
<ClCompile Include="fnmatch.cpp" />
<ClCompile Include="memaccess.cpp" />
<ClCompile Include="module.cpp" />
<ClCompile Include="net\metadata.cpp" />
......@@ -110,6 +111,7 @@
<ClInclude Include="dataaccessorimpl.h" />
<ClInclude Include="dia\diacallback.h" />
<ClInclude Include="dia\diawrapper.h" />
<ClInclude Include="fnmatch.h" />
<ClInclude Include="moduleimp.h" />
<ClInclude Include="net\metadata.h" />
<ClInclude Include="net\net.h" />
......
......@@ -139,6 +139,9 @@
<ClCompile Include="win\tagged.cpp">
<Filter>win</Filter>
</ClCompile>
<ClCompile Include="fnmatch.cpp">
<Filter>common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
......@@ -281,6 +284,9 @@
<ClInclude Include="..\include\kdlib\tagged.h">
<Filter>kdlib/include</Filter>
</ClInclude>
<ClInclude Include="fnmatch.h">
<Filter>common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="kdlib/include">
......
......@@ -10,33 +10,7 @@
#include "net/nettype.h"
#include "net/metadata.h"
#include <boost/regex.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace {
///////////////////////////////////////////////////////////////////////////////
const boost::wregex r1(L"\\?");
const boost::wregex r2(L"\\*");
const boost::wregex r3(L"\\.");
bool fnmatch( const std::wstring& pattern, const std::wstring& str)
{
std::wstring mask = pattern;
mask = boost::regex_replace(mask, r1, L".");
mask = boost::regex_replace(mask, r2, L".*");
mask = boost::regex_replace(mask, r3, L"\\.");
boost::wsmatch matchResult;
boost::wregex regEx(mask);
return boost::regex_match(str, matchResult, regEx);
}
///////////////////////////////////////////////////////////////////////////////
}
#include "fnmatch.h"
namespace kdlib {
......
......@@ -1014,6 +1014,10 @@ private:
virtual TypeInfoPtr getTypeByName(const std::wstring& name);
virtual TypeInfoEnumeratorPtr getTypeEnumerator(const std::wstring& mask = L"") {
NOT_IMPLEMENTED();
}
private:
SymbolSessionPtr m_symbolSession;
......
......@@ -367,3 +367,66 @@ TEST_F(ClangTest, Typedef)
ASSERT_EQ(L"_Test", typeProvider->getTypeByName(L"TEST")->getName() );
}
TEST_F(ClangTest, TypeProviderEnum)
{
const std::wstring src = L"#include \"../../../kdlib/include/test/testvars.h\"";
TypeInfoProviderPtr typeProvider;
ASSERT_NO_THROW( typeProvider = getTypeInfoProviderFromSource(src) );
TypeInfoEnumeratorPtr typeEnum;
size_t count;
ASSERT_NO_THROW( typeEnum = typeProvider->getTypeEnumerator() );
for ( count = 0; 0 != typeEnum->Next(); ++count);
EXPECT_LT(1000, count);
ASSERT_NO_THROW( typeEnum = typeProvider->getTypeEnumerator(L"struct*") );
for ( count = 0; 0 != typeEnum->Next(); ++count);
EXPECT_EQ(8, count);
}
static const wchar_t template_func_src1[] = L"\
\
template<typename T1, typename T2> \
T1 func(T2 v) { \
return v * 10; \
} \
";
static const wchar_t template_func_src2[] = L"\
\
template<typename T1, typename T2> \
T1 func(T2 v) { \
return v * 10; \
} \
\
template<> \
int func<int,int>(int v); \
";
static const wchar_t template_func_src3[] = L"\
\
template<typename T> \
class Generic { \
\
int intMethod() { \
return 0; \
} \
\
T tMethod() { \
return 0; \
} \
}; \
";
TEST_F(ClangTest, TemplateFunc)
{
EXPECT_THROW(compileType(template_func_src1, L"func"), TypeException );
EXPECT_NO_THROW( compileType(template_func_src2, L"func") );
EXPECT_THROW( compileType(template_func_src3, L"Generic::intMethod"), TypeException );
EXPECT_THROW( compileType(template_func_src3, L"Generic::tMethod"), TypeException );
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment