logic: improved recording of template member specializations
* implemented recording template member specialitation relations for fields, static variables, member classes and enums * added windows only tests that index whole projects (Bullet & Box2D) to prevent regression
This commit is contained in:
@@ -97,6 +97,16 @@ std::vector<std::string> TextAccess::readFile(const FilePath& filePath)
|
||||
}
|
||||
srcFile.close();
|
||||
|
||||
if (!result.empty())
|
||||
{
|
||||
std::string last = result.back().substr(0, result.back().size() - 1);
|
||||
result.pop_back();
|
||||
if (!last.empty())
|
||||
{
|
||||
result.push_back(last);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ DEF_TRAVERSE_TYPE(TypeLoc, {}, {})
|
||||
// additionally: skip implicit CXXRecordDecls (this does not skip template specializations).
|
||||
bool CxxAstVisitor::TraverseCXXRecordDecl(clang::CXXRecordDecl *d)
|
||||
{
|
||||
if (utility::isImplicit(d))
|
||||
if (utility::isImplicit(d) && d->getMemberSpecializationInfo() == nullptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -142,14 +142,35 @@ void CxxAstVisitorComponentIndexer::visitTagDecl(clang::TagDecl* d)
|
||||
definitionKind = utility::isImplicit(d) ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT;
|
||||
}
|
||||
|
||||
const SymbolKind symbolKind = utility::convertTagKind(d->getTagKind());
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
utility::convertTagKind(d->getTagKind()),
|
||||
symbolKind,
|
||||
getParseLocation(d->getLocation()),
|
||||
getParseLocationOfTagDeclBody(d),
|
||||
utility::convertAccessSpecifier(d->getAccess()),
|
||||
definitionKind
|
||||
);
|
||||
|
||||
if (clang::EnumDecl* enumDecl = clang::dyn_cast_or_null<clang::EnumDecl>(d))
|
||||
{
|
||||
recordTemplateMemberSpecialization(
|
||||
enumDecl->getMemberSpecializationInfo(),
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
getParseLocation(d->getLocation()),
|
||||
symbolKind
|
||||
);
|
||||
}
|
||||
if(clang::CXXRecordDecl* recordDecl = clang::dyn_cast_or_null<clang::CXXRecordDecl>(d))
|
||||
{
|
||||
recordTemplateMemberSpecialization(
|
||||
recordDecl->getMemberSpecializationInfo(),
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
getParseLocation(d->getLocation()),
|
||||
symbolKind
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,6 +226,13 @@ void CxxAstVisitorComponentIndexer::visitVarDecl(clang::VarDecl* d)
|
||||
utility::convertAccessSpecifier(d->getAccess()),
|
||||
utility::isImplicit(d) ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT
|
||||
);
|
||||
|
||||
recordTemplateMemberSpecialization(
|
||||
d->getMemberSpecializationInfo(),
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
getParseLocation(d->getLocation()),
|
||||
symbolKind
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,6 +248,30 @@ void CxxAstVisitorComponentIndexer::visitFieldDecl(clang::FieldDecl* d)
|
||||
utility::convertAccessSpecifier(d->getAccess()),
|
||||
utility::isImplicit(d) ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT
|
||||
);
|
||||
|
||||
if (clang::CXXRecordDecl* declaringRecordDecl = clang::dyn_cast_or_null<clang::CXXRecordDecl>(d->getParent()))
|
||||
{
|
||||
if (clang::CXXRecordDecl* declaringRecordTemplateDecl = declaringRecordDecl->getTemplateInstantiationPattern())
|
||||
{
|
||||
for (clang::FieldDecl* templateFieldDecl : declaringRecordTemplateDecl->fields())
|
||||
{
|
||||
if (d->getName() == templateFieldDecl->getName())
|
||||
{
|
||||
const NameHierarchy referencedName = getAstVisitor()->getDeclNameCache()->getValue(templateFieldDecl);
|
||||
|
||||
m_client->recordSymbol(referencedName, SYMBOL_FIELD, ACCESS_NONE, DEFINITION_NONE);
|
||||
|
||||
m_client->recordReference(
|
||||
REFERENCE_TEMPLATE_MEMBER_SPECIALIZATION,
|
||||
referencedName,
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
getParseLocation(d->getLocation())
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,24 +324,12 @@ void CxxAstVisitorComponentIndexer::visitCXXMethodDecl(clang::CXXMethodDecl* d)
|
||||
);
|
||||
}
|
||||
|
||||
clang::MemberSpecializationInfo* memberSpecializationInfo = d->getMemberSpecializationInfo();
|
||||
if (memberSpecializationInfo)
|
||||
{
|
||||
clang::NamedDecl* specializedNamedDecl = memberSpecializationInfo->getInstantiatedFrom();
|
||||
if (clang::isa<clang::FunctionDecl>(specializedNamedDecl))
|
||||
{
|
||||
const NameHierarchy referencedName = getAstVisitor()->getDeclNameCache()->getValue(specializedNamedDecl);
|
||||
|
||||
m_client->recordSymbol(referencedName, SYMBOL_FUNCTION, ACCESS_NONE, DEFINITION_NONE);
|
||||
|
||||
m_client->recordReference(
|
||||
REFERENCE_TEMPLATE_MEMBER_SPECIALIZATION,
|
||||
referencedName,
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
getParseLocation(d->getLocation())
|
||||
);
|
||||
}
|
||||
}
|
||||
recordTemplateMemberSpecialization(
|
||||
d->getMemberSpecializationInfo(),
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
getParseLocation(d->getLocation()),
|
||||
SYMBOL_FUNCTION
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,6 +683,25 @@ void CxxAstVisitorComponentIndexer::visitConstructorInitializer(clang::CXXCtorIn
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::recordTemplateMemberSpecialization(
|
||||
const clang::MemberSpecializationInfo* memberSpecializationInfo, const NameHierarchy& context, const ParseLocation& location, SymbolKind symbolKind)
|
||||
{
|
||||
if (memberSpecializationInfo != nullptr)
|
||||
{
|
||||
clang::NamedDecl* specializedNamedDecl = memberSpecializationInfo->getInstantiatedFrom();
|
||||
const NameHierarchy referencedName = getAstVisitor()->getDeclNameCache()->getValue(specializedNamedDecl);
|
||||
|
||||
m_client->recordSymbol(referencedName, symbolKind, ACCESS_NONE, DEFINITION_NONE);
|
||||
|
||||
m_client->recordReference(
|
||||
REFERENCE_TEMPLATE_MEMBER_SPECIALIZATION,
|
||||
referencedName,
|
||||
context,
|
||||
location
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ParseLocation CxxAstVisitorComponentIndexer::getParseLocationOfTagDeclBody(clang::TagDecl* decl) const
|
||||
{
|
||||
return getAstVisitor()->getParseLocationOfTagDeclBody(decl);
|
||||
|
||||
@@ -54,6 +54,13 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
void recordTemplateMemberSpecialization(
|
||||
const clang::MemberSpecializationInfo* memberSpecializationInfo,
|
||||
const NameHierarchy& context,
|
||||
const ParseLocation& location,
|
||||
SymbolKind symbolKind
|
||||
);
|
||||
|
||||
ParseLocation getParseLocationOfTagDeclBody(clang::TagDecl* decl) const;
|
||||
ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const;
|
||||
ParseLocation getParseLocation(const clang::SourceLocation& loc) const;
|
||||
|
||||
@@ -8,8 +8,9 @@ add_files(
|
||||
TestSuiteFixture.cpp
|
||||
TestSuiteFixture.h
|
||||
|
||||
ConfigManagerTestSuite.h
|
||||
CommandlineTestSuite.h
|
||||
ConfigManagerTestSuite.h
|
||||
CxxIndexSampleProjectsTestSuite.h
|
||||
CxxParserTestSuite.h
|
||||
CxxTypeNameTestSuite.h
|
||||
FileManagerTestSuite.h
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
#include "cxxtest/TestSuite.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "settings/ApplicationSettings.h"
|
||||
|
||||
|
||||
#include "utility/text/TextAccess.h"
|
||||
#include "utility/utility.h"
|
||||
#include "utility/utilityString.h"
|
||||
|
||||
#include "data/indexer/IndexerCommandCxxManual.h"
|
||||
#include "data/parser/cxx/CxxParser.h"
|
||||
|
||||
#include "helper/TestFileRegister.h"
|
||||
#include "helper/TestParserClient.h"
|
||||
|
||||
class CxxIndexSampleProjectsTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_index_box2d_project()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const bool updateExpectedOutput = false;
|
||||
|
||||
processSourceFile("Box2D", FilePath("Box2D/Collision/b2BroadPhase.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Collision/b2CollideCircle.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Collision/b2CollideEdge.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Collision/b2CollidePolygon.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Collision/b2Collision.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Collision/b2Distance.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Collision/b2DynamicTree.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Collision/b2TimeOfImpact.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Collision/Shapes/b2ChainShape.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Collision/Shapes/b2CircleShape.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Collision/Shapes/b2EdgeShape.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Collision/Shapes/b2PolygonShape.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Common/b2BlockAllocator.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Common/b2Draw.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Common/b2Math.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Common/b2Settings.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Common/b2StackAllocator.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Common/b2Timer.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/b2Body.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/b2ContactManager.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/b2Fixture.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/b2Island.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/b2World.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/b2WorldCallbacks.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Contacts/b2ChainAndCircleContact.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Contacts/b2CircleContact.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Contacts/b2Contact.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Contacts/b2ContactSolver.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Contacts/b2PolygonContact.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Joints/b2DistanceJoint.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Joints/b2FrictionJoint.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Joints/b2GearJoint.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Joints/b2Joint.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Joints/b2MotorJoint.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Joints/b2MouseJoint.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Joints/b2PrismaticJoint.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Joints/b2PulleyJoint.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Joints/b2RevoluteJoint.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Joints/b2RopeJoint.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Joints/b2WeldJoint.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Dynamics/Joints/b2WheelJoint.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Box2D", FilePath("Box2D/Rope/b2Rope.cpp"), updateExpectedOutput);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_index_bullet3_project()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const bool updateExpectedOutput = false;
|
||||
|
||||
processSourceFile("Bullet3", FilePath("Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Bullet3", FilePath("Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Bullet3", FilePath("Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Bullet3", FilePath("Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Bullet3", FilePath("Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Bullet3", FilePath("Bullet3Common/b3AlignedAllocator.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Bullet3", FilePath("Bullet3Common/b3Logging.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Bullet3", FilePath("Bullet3Common/b3Vector3.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Bullet3", FilePath("Bullet3Geometry/b3ConvexHullComputer.cpp"), updateExpectedOutput);
|
||||
processSourceFile("Bullet3", FilePath("Bullet3Geometry/b3GeometryUtil.cpp"), updateExpectedOutput);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
class DumpParserClient : public ParserClient
|
||||
{
|
||||
public:
|
||||
DumpParserClient()
|
||||
: m_dump("")
|
||||
{
|
||||
}
|
||||
|
||||
virtual Id recordSymbol(
|
||||
const NameHierarchy& symbolName, SymbolKind symbolKind,
|
||||
AccessKind access, DefinitionKind definitionKind)
|
||||
{
|
||||
m_dump += symbolKindToString(symbolKind) + " " + addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access) + "\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id recordSymbol(
|
||||
const NameHierarchy& symbolName, SymbolKind symbolKind,
|
||||
const ParseLocation& location,
|
||||
AccessKind access, DefinitionKind definitionKind)
|
||||
{
|
||||
m_dump += symbolKindToString(symbolKind) + " " + addLocationSuffix(addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access) + " [" + location.filePath.fileName(), location) + "]\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id recordSymbol(
|
||||
const NameHierarchy& symbolName, SymbolKind symbolKind,
|
||||
const ParseLocation& location, const ParseLocation& scopeLocation,
|
||||
AccessKind access, DefinitionKind definitionKind)
|
||||
{
|
||||
m_dump += symbolKindToString(symbolKind) + " " + addLocationSuffix(addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access) + " [" + location.filePath.fileName(), location, scopeLocation) + "]\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
void recordReference(
|
||||
ReferenceKind referenceKind, const NameHierarchy& referencedName, const NameHierarchy& contextName,
|
||||
const ParseLocation& location)
|
||||
{
|
||||
std::string contextNameString = contextName.getQualifiedNameWithSignature();
|
||||
if (FilePath(contextNameString).exists())
|
||||
{
|
||||
contextNameString = FilePath(contextNameString).fileName();
|
||||
}
|
||||
m_dump += referenceKindToString(referenceKind) + " " + addLocationSuffix(contextNameString + " -> " + referencedName.getQualifiedNameWithSignature() + " [" + location.filePath.fileName(), location) + "]\n";
|
||||
}
|
||||
|
||||
virtual void onError(const ParseLocation& location, const std::string& message, const std::string& commandline,
|
||||
bool fatal, bool indexed)
|
||||
{
|
||||
m_dump += "ERROR: " + addLocationSuffix(message + " [" + location.filePath.fileName(), location) + "]\n";
|
||||
}
|
||||
|
||||
virtual void onLocalSymbolParsed(const std::string& name, const ParseLocation& location)
|
||||
{
|
||||
m_dump += "LOCAL_SYMBOL: " + addLocationSuffix(name + " [" + location.filePath.fileName(), location) + "]\n";
|
||||
}
|
||||
|
||||
virtual void onFileParsed(const FileInfo& fileInfo)
|
||||
{
|
||||
m_dump += "FILE: " + fileInfo.path.fileName() + "\n";
|
||||
}
|
||||
|
||||
virtual void onCommentParsed(const ParseLocation& location)
|
||||
{
|
||||
m_dump += "COMMENT: " + addLocationSuffix("comment [" + location.filePath.fileName(), location) + "]\n";
|
||||
}
|
||||
|
||||
std::string m_dump;
|
||||
|
||||
private:
|
||||
std::string symbolKindToString(SymbolKind symbolKind) const
|
||||
{
|
||||
switch (symbolKind)
|
||||
{
|
||||
case SYMBOL_BUILTIN_TYPE:
|
||||
return "SYMBOL_BUILTIN_TYPE";
|
||||
case SYMBOL_CLASS:
|
||||
return "SYMBOL_CLASS";
|
||||
case SYMBOL_ENUM:
|
||||
return "SYMBOL_ENUM";
|
||||
case SYMBOL_ENUM_CONSTANT:
|
||||
return "SYMBOL_ENUM_CONSTANT";
|
||||
case SYMBOL_FIELD:
|
||||
return "SYMBOL_FIELD";
|
||||
case SYMBOL_FUNCTION:
|
||||
return "SYMBOL_FUNCTION";
|
||||
case SYMBOL_GLOBAL_VARIABLE:
|
||||
return "SYMBOL_GLOBAL_VARIABLE";
|
||||
case SYMBOL_INTERFACE:
|
||||
return "SYMBOL_INTERFACE";
|
||||
case SYMBOL_MACRO:
|
||||
return "SYMBOL_MACRO";
|
||||
case SYMBOL_METHOD:
|
||||
return "SYMBOL_METHOD";
|
||||
case SYMBOL_NAMESPACE:
|
||||
return "SYMBOL_NAMESPACE";
|
||||
case SYMBOL_PACKAGE:
|
||||
return "SYMBOL_PACKAGE";
|
||||
case SYMBOL_STRUCT:
|
||||
return "SYMBOL_STRUCT";
|
||||
case SYMBOL_TEMPLATE_PARAMETER:
|
||||
return "SYMBOL_TEMPLATE_PARAMETER";
|
||||
case SYMBOL_TYPEDEF:
|
||||
return "SYMBOL_TYPEDEF";
|
||||
case SYMBOL_TYPE_PARAMETER:
|
||||
return "SYMBOL_TYPE_PARAMETER";
|
||||
case SYMBOL_UNION:
|
||||
return "SYMBOL_UNION";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "SYMBOL_NON_INDEXED";
|
||||
}
|
||||
|
||||
std::string referenceKindToString(ReferenceKind referenceKind) const
|
||||
{
|
||||
switch (referenceKind)
|
||||
{
|
||||
case REFERENCE_TYPE_USAGE:
|
||||
return "REFERENCE_TYPE_USAGE";
|
||||
case REFERENCE_USAGE:
|
||||
return "REFERENCE_USAGE";
|
||||
case REFERENCE_CALL:
|
||||
return "REFERENCE_CALL";
|
||||
case REFERENCE_INHERITANCE:
|
||||
return "REFERENCE_INHERITANCE";
|
||||
case REFERENCE_OVERRIDE:
|
||||
return "REFERENCE_OVERRIDE";
|
||||
case REFERENCE_TEMPLATE_ARGUMENT:
|
||||
return "REFERENCE_TEMPLATE_ARGUMENT";
|
||||
case REFERENCE_TYPE_ARGUMENT:
|
||||
return "REFERENCE_TYPE_ARGUMENT";
|
||||
case REFERENCE_TEMPLATE_DEFAULT_ARGUMENT:
|
||||
return "REFERENCE_TEMPLATE_DEFAULT_ARGUMENT";
|
||||
case REFERENCE_TEMPLATE_SPECIALIZATION:
|
||||
return "REFERENCE_TEMPLATE_SPECIALIZATION";
|
||||
case REFERENCE_TEMPLATE_MEMBER_SPECIALIZATION:
|
||||
return "REFERENCE_TEMPLATE_MEMBER_SPECIALIZATION";
|
||||
case REFERENCE_INCLUDE:
|
||||
return "REFERENCE_INCLUDE";
|
||||
case REFERENCE_IMPORT:
|
||||
return "REFERENCE_IMPORT";
|
||||
case REFERENCE_MACRO_USAGE:
|
||||
return "REFERENCE_MACRO_USAGE";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "REFERENCE_UNDEFINED";
|
||||
}
|
||||
};
|
||||
|
||||
void processSourceFile(const std::string& projectName, const FilePath& sourceFilePath, const bool updateExpectedOutput)
|
||||
{
|
||||
const FilePath projectDataRoot = FilePath("data/CxxIndexSampleProjectsTestSuite/" + projectName);
|
||||
const FilePath projectDataSrcRoot = projectDataRoot.concat(FilePath("src"));
|
||||
const FilePath projectDataExpectedOutputRoot = projectDataRoot.concat(FilePath("expected_output"));
|
||||
|
||||
std::shared_ptr<TextAccess> output = parseCode(projectDataSrcRoot.concat(sourceFilePath), projectDataSrcRoot);
|
||||
|
||||
FilePath expectedOutputFilePath = projectDataExpectedOutputRoot.concat(FilePath(utility::replace(sourceFilePath.withoutExtension().str() + ".txt", "/", "_")));
|
||||
if (updateExpectedOutput || !expectedOutputFilePath.exists())
|
||||
{
|
||||
std::ofstream expectedOutputFile;
|
||||
expectedOutputFile.open(expectedOutputFilePath.str());
|
||||
expectedOutputFile << output->getText();
|
||||
expectedOutputFile.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<TextAccess> expectedOutput = TextAccess::createFromFile(expectedOutputFilePath);
|
||||
TSM_ASSERT_EQUALS("Output does not match the expected line count for file " + sourceFilePath.str() + " in project " + projectName, expectedOutput->getLineCount(), output->getLineCount());
|
||||
if (expectedOutput->getLineCount() == output->getLineCount())
|
||||
{
|
||||
for (size_t i = 1; i <= expectedOutput->getLineCount(); i++)
|
||||
{
|
||||
TS_ASSERT_EQUALS(expectedOutput->getLine(i), output->getLine(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<TextAccess> parseCode(const FilePath& sourceFilePath, const FilePath& projectDataSrcRoot)
|
||||
{
|
||||
std::set<FilePath> indexedPaths = { projectDataSrcRoot };
|
||||
std::set<FilePath> excludedPaths = { };
|
||||
|
||||
std::shared_ptr<FileRegister> fileRegister = std::make_shared<FileRegister>(
|
||||
FileRegisterStateData(),
|
||||
sourceFilePath,
|
||||
indexedPaths,
|
||||
excludedPaths
|
||||
);
|
||||
|
||||
std::shared_ptr<DumpParserClient> parserClient = std::make_shared<DumpParserClient>();
|
||||
|
||||
CxxParser parser(parserClient, fileRegister);
|
||||
|
||||
std::shared_ptr<IndexerCommandCxxManual> command = std::make_shared<IndexerCommandCxxManual>(
|
||||
sourceFilePath,
|
||||
indexedPaths,
|
||||
excludedPaths,
|
||||
"c++1z",
|
||||
utility::concat(std::vector<FilePath> { projectDataSrcRoot }, ApplicationSettings::getInstance()->getHeaderSearchPathsExpanded()),
|
||||
ApplicationSettings::getInstance()->getFrameworkSearchPathsExpanded(),
|
||||
std::vector<std::string> { "--target=x86_64-pc-windows-msvc" },
|
||||
true
|
||||
);
|
||||
|
||||
parser.buildIndex(command);
|
||||
|
||||
return TextAccess::createFromString(parserClient->m_dump);
|
||||
}
|
||||
};
|
||||
@@ -2633,7 +2633,7 @@ public:
|
||||
));
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_member_specialization_of_implicit_template_specialization()
|
||||
void test_cxx_parser_finds_template_member_specialization_for_method_of_implicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
@@ -2653,6 +2653,89 @@ public:
|
||||
));
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_member_specialization_for_static_variable_of_implicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" static T foo;\n"
|
||||
"};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" A<int> a;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->templateMemberSpecializations, "static int A<int>::foo -> static A<typename T>::T A<typename T>::foo <5:11 5:13>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_member_specialization_for_field_of_implicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" T foo;\n"
|
||||
"};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" A<int> a;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->templateMemberSpecializations, "int A<int>::foo -> A<typename T>::T A<typename T>::foo <5:4 5:6>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_member_specialization_for_field_of_member_class_of_implicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" class B {\n"
|
||||
" public:\n"
|
||||
" T foo;\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" A<int>::B b;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->templateMemberSpecializations, "int A<int>::B::foo -> A<typename T>::T A<typename T>::B::foo <7:5 7:7>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_member_specialization_for_member_class_of_implicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" class B {};\n"
|
||||
"};\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" A<int> a;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->templateMemberSpecializations, "A<int>::B -> A<typename T>::B <5:8 5:8>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_type_template_argument_of_explicit_template_specialization()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
|
||||
Reference in New Issue
Block a user