src: split CxxAstVisitor into component based indexing system
* also: added logging for sqlite exceptions
This commit is contained in:
+174
-125
@@ -17,7 +17,7 @@ SqliteStorage::SqliteStorage(const FilePath& dbFilePath)
|
||||
{
|
||||
m_database.open(m_dbFilePath.str().c_str());
|
||||
|
||||
m_database.execDML("PRAGMA foreign_keys=ON;");
|
||||
executeStatement("PRAGMA foreign_keys=ON;");
|
||||
|
||||
m_mode = STORAGE_MODE_UNKNOWN;
|
||||
|
||||
@@ -69,14 +69,14 @@ SqliteStorage::~SqliteStorage()
|
||||
|
||||
void SqliteStorage::setup()
|
||||
{
|
||||
m_database.execDML("PRAGMA foreign_keys=ON;");
|
||||
executeStatement("PRAGMA foreign_keys=ON;");
|
||||
setupTables();
|
||||
m_mode = STORAGE_MODE_UNKNOWN;
|
||||
}
|
||||
|
||||
void SqliteStorage::clear()
|
||||
{
|
||||
m_database.execDML("PRAGMA foreign_keys=OFF;");
|
||||
executeStatement("PRAGMA foreign_keys=OFF;");
|
||||
clearTables();
|
||||
|
||||
setup();
|
||||
@@ -106,29 +106,22 @@ void SqliteStorage::setMode(const StorageModeType mode)
|
||||
|
||||
void SqliteStorage::beginTransaction()
|
||||
{
|
||||
m_database.execDML("BEGIN TRANSACTION;");
|
||||
executeStatement("BEGIN TRANSACTION;");
|
||||
}
|
||||
|
||||
void SqliteStorage::commitTransaction()
|
||||
{
|
||||
m_database.execDML("COMMIT TRANSACTION;");
|
||||
executeStatement("COMMIT TRANSACTION;");
|
||||
}
|
||||
|
||||
void SqliteStorage::rollbackTransaction()
|
||||
{
|
||||
m_database.execDML("ROLLBACK TRANSACTION;");
|
||||
executeStatement("ROLLBACK TRANSACTION;");
|
||||
}
|
||||
|
||||
void SqliteStorage::optimizeMemory() const
|
||||
{
|
||||
try
|
||||
{
|
||||
m_database.execDML("VACUUM;");
|
||||
}
|
||||
catch(CppSQLite3Exception e)
|
||||
{
|
||||
LOG_ERROR(e.errorMessage());
|
||||
}
|
||||
executeStatement("VACUUM;");
|
||||
}
|
||||
|
||||
FilePath SqliteStorage::getDbFilePath() const
|
||||
@@ -177,25 +170,21 @@ void SqliteStorage::setVersion()
|
||||
|
||||
Id SqliteStorage::addEdge(int type, Id sourceNodeId, Id targetNodeId)
|
||||
{
|
||||
m_database.execDML(
|
||||
"INSERT INTO element(id) VALUES(NULL);"
|
||||
);
|
||||
executeStatement("INSERT INTO element(id) VALUES(NULL);");
|
||||
Id id = m_database.lastRowId();
|
||||
|
||||
m_database.execDML((
|
||||
executeStatement(
|
||||
"INSERT INTO edge(id, type, source_node_id, target_node_id) VALUES("
|
||||
+ std::to_string(id) + ", " + std::to_string(type) + ", "
|
||||
+ std::to_string(sourceNodeId) + ", " + std::to_string(targetNodeId) + ");"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
Id SqliteStorage::addNode(int type, const std::string& serializedName, int definitionType)
|
||||
{
|
||||
m_database.execDML(
|
||||
"INSERT INTO element(id) VALUES(NULL);"
|
||||
);
|
||||
executeStatement("INSERT INTO element(id) VALUES(NULL);");
|
||||
Id id = m_database.lastRowId();
|
||||
|
||||
CppSQLite3Statement stmt = m_database.compileStatement((
|
||||
@@ -204,7 +193,7 @@ Id SqliteStorage::addNode(int type, const std::string& serializedName, int defin
|
||||
).c_str());
|
||||
|
||||
stmt.bind(1, serializedName.c_str());
|
||||
stmt.execDML();
|
||||
executeStatement(stmt);
|
||||
|
||||
return id;
|
||||
}
|
||||
@@ -215,10 +204,10 @@ Id SqliteStorage::addFile(const std::string& serializedName, const std::string&
|
||||
std::shared_ptr<TextAccess> content = TextAccess::createFromFile(filePath);
|
||||
unsigned int loc = content->getLineCount();
|
||||
|
||||
m_database.execDML((
|
||||
executeStatement(
|
||||
"INSERT INTO file(id, path, modification_time, loc) VALUES("
|
||||
+ std::to_string(id) + ", '" + filePath + "', '" + modificationTime + "', " + std::to_string(loc) + ");"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
CppSQLite3Statement stmt = m_database.compileStatement((
|
||||
"INSERT INTO filecontent(id, content) VALUES("
|
||||
@@ -226,16 +215,14 @@ Id SqliteStorage::addFile(const std::string& serializedName, const std::string&
|
||||
).c_str());
|
||||
|
||||
stmt.bind(1, content->getText().c_str());
|
||||
stmt.execDML();
|
||||
executeStatement(stmt);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
Id SqliteStorage::addLocalSymbol(const std::string& name)
|
||||
{
|
||||
m_database.execDML(
|
||||
"INSERT INTO element(id) VALUES(NULL);"
|
||||
);
|
||||
executeStatement("INSERT INTO element(id) VALUES(NULL);");
|
||||
Id id = m_database.lastRowId();
|
||||
|
||||
CppSQLite3Statement stmt = m_database.compileStatement((
|
||||
@@ -244,7 +231,7 @@ Id SqliteStorage::addLocalSymbol(const std::string& name)
|
||||
).c_str());
|
||||
|
||||
stmt.bind(1, name.c_str());
|
||||
stmt.execDML();
|
||||
executeStatement(stmt);
|
||||
|
||||
return id;
|
||||
}
|
||||
@@ -252,12 +239,12 @@ Id SqliteStorage::addLocalSymbol(const std::string& name)
|
||||
Id SqliteStorage::addSourceLocation(
|
||||
Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol, int type)
|
||||
{
|
||||
m_database.execDML((
|
||||
executeStatement(
|
||||
"INSERT INTO source_location(id, file_node_id, start_line, start_column, end_line, end_column, type) "
|
||||
"VALUES(NULL, " + std::to_string(fileNodeId) + ", "
|
||||
+ std::to_string(startLine) + ", " + std::to_string(startCol) + ", "
|
||||
+ std::to_string(endLine) + ", " + std::to_string(endCol) + ", " + std::to_string(type) + ");"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
return m_database.lastRowId();
|
||||
}
|
||||
@@ -281,22 +268,22 @@ bool SqliteStorage::addOccurrence(Id elementId, Id sourceLocationId)
|
||||
|
||||
Id SqliteStorage::addComponentAccess(Id nodeId, int type)
|
||||
{
|
||||
m_database.execDML((
|
||||
executeStatement(
|
||||
"INSERT INTO component_access(id, node_id, type) "
|
||||
"VALUES (NULL, " + std::to_string(nodeId) + ", " + std::to_string(type) + ");"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
return m_database.lastRowId();
|
||||
}
|
||||
|
||||
Id SqliteStorage::addCommentLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol)
|
||||
{
|
||||
m_database.execDML((
|
||||
executeStatement(
|
||||
"INSERT INTO comment_location(id, file_node_id, start_line, start_column, end_line, end_column) "
|
||||
"VALUES(NULL, " + std::to_string(fileNodeId) + ", "
|
||||
+ std::to_string(startLine) + ", " + std::to_string(startCol) + ", "
|
||||
+ std::to_string(endLine) + ", " + std::to_string(endCol) + ");"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
return m_database.lastRowId();
|
||||
}
|
||||
@@ -307,7 +294,6 @@ Id SqliteStorage::addError(const std::string& message, const FilePath& filePath,
|
||||
|
||||
// check for duplicate
|
||||
CppSQLite3Statement stmt = m_database.compileStatement((
|
||||
//CppSQLite3Query q = m_database.execQuery((
|
||||
"SELECT * FROM error WHERE "
|
||||
"message == ? AND "
|
||||
"fatal == " + std::to_string(fatal) + " AND "
|
||||
@@ -317,7 +303,7 @@ Id SqliteStorage::addError(const std::string& message, const FilePath& filePath,
|
||||
).c_str());
|
||||
|
||||
stmt.bind(1, sanitizedMessage.c_str());
|
||||
CppSQLite3Query q = stmt.execQuery();
|
||||
CppSQLite3Query q = executeQuery(stmt);
|
||||
|
||||
if (!q.eof())
|
||||
{
|
||||
@@ -333,7 +319,7 @@ Id SqliteStorage::addError(const std::string& message, const FilePath& filePath,
|
||||
).c_str());
|
||||
|
||||
stmt.bind(1, sanitizedMessage.c_str());
|
||||
stmt.execDML();
|
||||
executeStatement(stmt);
|
||||
|
||||
return m_database.lastRowId();
|
||||
}
|
||||
@@ -347,24 +333,24 @@ void SqliteStorage::removeElement(Id id)
|
||||
|
||||
void SqliteStorage::removeElements(const std::vector<Id>& ids)
|
||||
{
|
||||
m_database.execDML((
|
||||
executeStatement(
|
||||
"DELETE FROM element WHERE id IN (" + utility::join(utility::toStrings(ids), ',') + ");"
|
||||
).c_str());
|
||||
);
|
||||
}
|
||||
|
||||
void SqliteStorage::removeElementsWithLocationInFiles(const std::vector<Id>& fileIds)
|
||||
{
|
||||
// preparing
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.element_id_to_clear;");
|
||||
executeStatement("DROP TABLE IF EXISTS main.element_id_to_clear;");
|
||||
|
||||
m_database.execDML(
|
||||
executeStatement(
|
||||
"CREATE TABLE IF NOT EXISTS element_id_to_clear("
|
||||
"id INTEGER NOT NULL, "
|
||||
"PRIMARY KEY(id));"
|
||||
);
|
||||
|
||||
// store ids of all elements located in fileIds into element_id_to_clear
|
||||
m_database.execDML((
|
||||
executeStatement(
|
||||
"INSERT INTO element_id_to_clear "
|
||||
" SELECT occurrence.element_id "
|
||||
" FROM occurrence "
|
||||
@@ -373,85 +359,84 @@ void SqliteStorage::removeElementsWithLocationInFiles(const std::vector<Id>& fil
|
||||
" ) "
|
||||
" WHERE source_location.file_node_id IN (" + utility::join(utility::toStrings(fileIds), ',') + ")"
|
||||
" GROUP BY (occurrence.element_id)"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
// delete all edges in element_id_to_clear
|
||||
m_database.execDML(
|
||||
executeStatement(
|
||||
"DELETE FROM element WHERE element.id IN (SELECT element_id_to_clear.id FROM element_id_to_clear INNER JOIN edge ON (element_id_to_clear.id = edge.id))"
|
||||
);
|
||||
|
||||
// delete all edges originating from element_id_to_clear
|
||||
m_database.execDML(
|
||||
executeStatement(
|
||||
"DELETE FROM element WHERE element.id IN (SELECT id FROM edge WHERE source_node_id IN (SELECT id FROM element_id_to_clear))"
|
||||
);
|
||||
|
||||
// remove all edges from element_id_to_clear (they have been cleared by now and we can disregard them)
|
||||
m_database.execDML(
|
||||
executeStatement(
|
||||
"DELETE FROM element_id_to_clear WHERE id IN ("
|
||||
" SELECT id FROM edge"
|
||||
")"
|
||||
);
|
||||
|
||||
// remove all files from element_id_to_clear (they will be cleared later)
|
||||
m_database.execDML(
|
||||
executeStatement(
|
||||
"DELETE FROM element_id_to_clear WHERE id IN ("
|
||||
" SELECT id FROM file"
|
||||
")"
|
||||
);
|
||||
|
||||
// delete source locations from fileIds (this also deletes the respective occurrences)
|
||||
m_database.execDML((
|
||||
executeStatement(
|
||||
"DELETE FROM source_location WHERE file_node_id IN (" + utility::join(utility::toStrings(fileIds), ',') + ");"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
// remove all ids from element_id_to_clear that still have occurrences
|
||||
m_database.execDML(
|
||||
executeStatement(
|
||||
"DELETE FROM element_id_to_clear WHERE id IN ("
|
||||
" SELECT element_id_to_clear.id FROM element_id_to_clear INNER JOIN occurrence ON element_id_to_clear.id = occurrence.element_id"
|
||||
")"
|
||||
);
|
||||
|
||||
// remove all ids from element_id_to_clear that still have an edge pointing to them
|
||||
m_database.execDML(
|
||||
executeStatement(
|
||||
"DELETE FROM element_id_to_clear WHERE id IN ("
|
||||
" SELECT target_node_id FROM edge"
|
||||
")"
|
||||
);
|
||||
|
||||
// delete all elements that are still listed in element_id_to_clear
|
||||
m_database.execDML(
|
||||
executeStatement(
|
||||
"DELETE FROM element WHERE id IN ("
|
||||
" SELECT id FROM element_id_to_clear"
|
||||
")"
|
||||
);
|
||||
|
||||
// cleaning up
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.element_id_to_clear;");
|
||||
|
||||
executeStatement("DROP TABLE IF EXISTS main.element_id_to_clear;");
|
||||
}
|
||||
|
||||
void SqliteStorage::removeErrorsInFiles(const std::vector<FilePath>& filePaths)
|
||||
{
|
||||
m_database.execDML((
|
||||
executeStatement(
|
||||
"DELETE FROM error WHERE file_path IN ('" + utility::join(utility::toStrings(filePaths), "', '") + "');"
|
||||
).c_str());
|
||||
);
|
||||
}
|
||||
|
||||
bool SqliteStorage::isEdge(Id elementId) const
|
||||
{
|
||||
int count = m_database.execScalar(("SELECT count(*) FROM edge WHERE id = " + std::to_string(elementId) + ";").c_str());
|
||||
int count = executeScalar("SELECT count(*) FROM edge WHERE id = " + std::to_string(elementId) + ";");
|
||||
return (count > 0);
|
||||
}
|
||||
|
||||
bool SqliteStorage::isNode(Id elementId) const
|
||||
{
|
||||
int count = m_database.execScalar(("SELECT count(*) FROM node WHERE id = " + std::to_string(elementId) + ";").c_str());
|
||||
int count = executeScalar("SELECT count(*) FROM node WHERE id = " + std::to_string(elementId) + ";");
|
||||
return (count > 0);
|
||||
}
|
||||
|
||||
bool SqliteStorage::isFile(Id elementId) const
|
||||
{
|
||||
int count = m_database.execScalar(("SELECT count(*) FROM file WHERE id = " + std::to_string(elementId) + ";").c_str());
|
||||
int count = executeScalar("SELECT count(*) FROM file WHERE id = " + std::to_string(elementId) + ";");
|
||||
return (count > 0);
|
||||
}
|
||||
|
||||
@@ -535,7 +520,7 @@ StorageNode SqliteStorage::getNodeBySerializedName(const std::string& serialized
|
||||
);
|
||||
|
||||
stmt.bind(1, serializedName.c_str());
|
||||
CppSQLite3Query q = stmt.execQuery();
|
||||
CppSQLite3Query q = executeQuery(stmt);
|
||||
|
||||
if (!q.eof())
|
||||
{
|
||||
@@ -580,19 +565,12 @@ std::vector<StorageFile> SqliteStorage::getFilesByPaths(const std::vector<FilePa
|
||||
|
||||
std::shared_ptr<TextAccess> SqliteStorage::getFileContentById(Id fileId) const
|
||||
{
|
||||
try
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT content FROM filecontent WHERE id = '" + std::to_string(fileId) + "';"
|
||||
);
|
||||
if (!q.eof())
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
"SELECT content FROM filecontent WHERE id = '" + std::to_string(fileId) + "';"
|
||||
).c_str());
|
||||
if (!q.eof())
|
||||
{
|
||||
return TextAccess::createFromString(q.getStringField(0, ""));
|
||||
}
|
||||
}
|
||||
catch (CppSQLite3Exception& e)
|
||||
{
|
||||
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
|
||||
return TextAccess::createFromString(q.getStringField(0, ""));
|
||||
}
|
||||
|
||||
return TextAccess::createFromString("");
|
||||
@@ -602,12 +580,12 @@ std::shared_ptr<TextAccess> SqliteStorage::getFileContentByPath(const std::strin
|
||||
{
|
||||
try
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT filecontent.content "
|
||||
"FROM filecontent "
|
||||
"INNER JOIN file ON filecontent.id = file.id "
|
||||
"WHERE file.path = '" + filePath + "';"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
if (!q.eof())
|
||||
{
|
||||
@@ -624,16 +602,16 @@ std::shared_ptr<TextAccess> SqliteStorage::getFileContentByPath(const std::strin
|
||||
|
||||
void SqliteStorage::setNodeType(int type, Id nodeId)
|
||||
{
|
||||
m_database.execDML((
|
||||
executeStatement(
|
||||
"UPDATE node SET type = " + std::to_string(type) + " WHERE id == " + std::to_string(nodeId) + ";"
|
||||
).c_str());
|
||||
);
|
||||
}
|
||||
|
||||
void SqliteStorage::setNodeDefinitionType(int definitionType, Id nodeId)
|
||||
{
|
||||
m_database.execDML((
|
||||
executeStatement(
|
||||
"UPDATE node SET definition_type = " + std::to_string(definitionType) + " WHERE id == " + std::to_string(nodeId) + ";"
|
||||
).c_str());
|
||||
);
|
||||
}
|
||||
|
||||
StorageSourceLocation SqliteStorage::getSourceLocationById(const Id id) const
|
||||
@@ -701,7 +679,7 @@ std::vector<std::pair<StorageSourceLocation, Id>> SqliteStorage::getSourceLocati
|
||||
|
||||
std::vector<std::pair<StorageSourceLocation, Id>> SqliteStorage::getAllSourceLocationsAndElementIds(const std::string& query) const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT "
|
||||
"source_location.id, "
|
||||
"source_location.file_node_id, "
|
||||
@@ -713,7 +691,7 @@ std::vector<std::pair<StorageSourceLocation, Id>> SqliteStorage::getAllSourceLoc
|
||||
"occurrence.element_id "
|
||||
"FROM source_location "
|
||||
"INNER JOIN occurrence ON occurrence.source_location_id = source_location.id " + query + ";"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
std::vector<std::pair<StorageSourceLocation, Id>> ret;
|
||||
while (!q.eof())
|
||||
@@ -748,7 +726,7 @@ std::vector<std::pair<StorageSourceLocation, Id>> SqliteStorage::getAllSourceLoc
|
||||
|
||||
std::vector<std::pair<StorageSourceLocation, Id>> SqliteStorage::getAllSourceLocationsAndElementIdsForFileId(Id fileNodeId) const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT "
|
||||
"source_location.id, "
|
||||
"source_location.file_node_id, "
|
||||
@@ -758,7 +736,7 @@ std::vector<std::pair<StorageSourceLocation, Id>> SqliteStorage::getAllSourceLoc
|
||||
"source_location.end_column, "
|
||||
"source_location.type "
|
||||
"FROM source_location WHERE source_location.file_node_id == " + std::to_string(fileNodeId) + ";"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
std::map<Id, StorageSourceLocation> locations;
|
||||
std::vector<Id> locationIds;
|
||||
@@ -791,12 +769,12 @@ std::vector<std::pair<StorageSourceLocation, Id>> SqliteStorage::getAllSourceLoc
|
||||
q.nextRow();
|
||||
}
|
||||
|
||||
CppSQLite3Query q2 = m_database.execQuery((
|
||||
CppSQLite3Query q2 = executeQuery(
|
||||
"SELECT "
|
||||
"occurrence.element_id, "
|
||||
"occurrence.source_location_id "
|
||||
"FROM occurrence WHERE occurrence.source_location_id IN (" + utility::join(utility::toStrings(locationIds), ',') + ");"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
std::vector<std::pair<StorageSourceLocation, Id>> ret;
|
||||
while (!q2.eof())
|
||||
@@ -891,43 +869,50 @@ std::vector<StorageError> SqliteStorage::getAllErrors() const
|
||||
|
||||
int SqliteStorage::getNodeCount() const
|
||||
{
|
||||
return m_database.execScalar("SELECT COUNT(*) FROM node;");
|
||||
return executeScalar("SELECT COUNT(*) FROM node;");
|
||||
}
|
||||
|
||||
int SqliteStorage::getEdgeCount() const
|
||||
{
|
||||
return m_database.execScalar("SELECT COUNT(*) FROM edge;");
|
||||
return executeScalar("SELECT COUNT(*) FROM edge;");
|
||||
}
|
||||
|
||||
int SqliteStorage::getFileCount() const
|
||||
{
|
||||
return m_database.execScalar("SELECT COUNT(*) FROM file;");
|
||||
return executeScalar("SELECT COUNT(*) FROM file;");
|
||||
}
|
||||
|
||||
int SqliteStorage::getFileLOCCount() const
|
||||
{
|
||||
return m_database.execScalar("SELECT SUM(loc) FROM file;");
|
||||
return executeScalar("SELECT SUM(loc) FROM file;");
|
||||
}
|
||||
|
||||
int SqliteStorage::getSourceLocationCount() const
|
||||
{
|
||||
return m_database.execScalar("SELECT COUNT(*) FROM source_location;");
|
||||
return executeScalar("SELECT COUNT(*) FROM source_location;");
|
||||
}
|
||||
|
||||
void SqliteStorage::clearTables()
|
||||
{
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.error;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.comment_location;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.component_access;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.occurrence;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.source_location;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.local_symbol;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.filecontent;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.file;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.node;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.edge;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.element;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.meta;");
|
||||
try
|
||||
{
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.error;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.comment_location;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.component_access;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.occurrence;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.source_location;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.local_symbol;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.filecontent;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.file;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.node;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.edge;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.element;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.meta;");
|
||||
}
|
||||
catch (CppSQLite3Exception& e)
|
||||
{
|
||||
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
void SqliteStorage::setupTables()
|
||||
@@ -1059,11 +1044,75 @@ void SqliteStorage::setupTables()
|
||||
}
|
||||
}
|
||||
|
||||
void SqliteStorage::executeStatement(const std::string& statement) const
|
||||
{
|
||||
try
|
||||
{
|
||||
m_database.execDML(statement.c_str());
|
||||
}
|
||||
catch(CppSQLite3Exception e)
|
||||
{
|
||||
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
void SqliteStorage::executeStatement(CppSQLite3Statement& statement) const
|
||||
{
|
||||
try
|
||||
{
|
||||
statement.execDML();
|
||||
}
|
||||
catch(CppSQLite3Exception e)
|
||||
{
|
||||
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
int SqliteStorage::executeScalar(const std::string& statement) const
|
||||
{
|
||||
int ret = 0;
|
||||
try
|
||||
{
|
||||
ret = m_database.execScalar(statement.c_str());
|
||||
}
|
||||
catch(CppSQLite3Exception e)
|
||||
{
|
||||
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CppSQLite3Query SqliteStorage::executeQuery(const std::string& query) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_database.execQuery(query.c_str());
|
||||
}
|
||||
catch(CppSQLite3Exception e)
|
||||
{
|
||||
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
|
||||
}
|
||||
return CppSQLite3Query();
|
||||
}
|
||||
|
||||
CppSQLite3Query SqliteStorage::executeQuery(CppSQLite3Statement& statement) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return statement.execQuery();
|
||||
}
|
||||
catch(CppSQLite3Exception e)
|
||||
{
|
||||
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
|
||||
}
|
||||
return CppSQLite3Query();
|
||||
}
|
||||
|
||||
bool SqliteStorage::hasTable(const std::string& tableName) const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='" + tableName + "';"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
if (!q.eof())
|
||||
{
|
||||
@@ -1077,7 +1126,7 @@ std::string SqliteStorage::getMetaValue(const std::string& key) const
|
||||
{
|
||||
if (hasTable("meta"))
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery(("SELECT value FROM meta WHERE key = '" + key + "';").c_str());
|
||||
CppSQLite3Query q = executeQuery("SELECT value FROM meta WHERE key = '" + key + "';");
|
||||
|
||||
if (!q.eof())
|
||||
{
|
||||
@@ -1099,7 +1148,7 @@ void SqliteStorage::insertOrUpdateMetaValue(const std::string& key, const std::s
|
||||
stmt.bind(1, key.c_str());
|
||||
stmt.bind(2, key.c_str());
|
||||
stmt.bind(3, value.c_str());
|
||||
stmt.execDML();
|
||||
executeStatement(stmt);
|
||||
}
|
||||
|
||||
size_t SqliteStorage::getStorageVersion() const
|
||||
@@ -1139,10 +1188,10 @@ void SqliteStorage::setApplicationVersion()
|
||||
template <>
|
||||
std::vector<StorageFile> SqliteStorage::getAll<StorageFile>(const std::string& query) const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT file.id, node.serialized_name, file.path, file.modification_time FROM file "
|
||||
"INNER JOIN node ON file.id = node.id " + query + ";"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
std::vector<StorageFile> files;
|
||||
while (!q.eof())
|
||||
@@ -1165,9 +1214,9 @@ std::vector<StorageFile> SqliteStorage::getAll<StorageFile>(const std::string& q
|
||||
template <>
|
||||
std::vector<StorageEdge> SqliteStorage::getAll<StorageEdge>(const std::string& query) const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT id, type, source_node_id, target_node_id FROM edge " + query + ";"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
std::vector<StorageEdge> edges;
|
||||
while (!q.eof())
|
||||
@@ -1190,9 +1239,9 @@ std::vector<StorageEdge> SqliteStorage::getAll<StorageEdge>(const std::string& q
|
||||
template <>
|
||||
std::vector<StorageNode> SqliteStorage::getAll<StorageNode>(const std::string& query) const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT id, type, serialized_name, definition_type FROM node " + query + ";"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
std::vector<StorageNode> nodes;
|
||||
while (!q.eof())
|
||||
@@ -1215,9 +1264,9 @@ std::vector<StorageNode> SqliteStorage::getAll<StorageNode>(const std::string& q
|
||||
template <>
|
||||
std::vector<StorageLocalSymbol> SqliteStorage::getAll<StorageLocalSymbol>(const std::string& query) const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT id, name FROM local_symbol " + query + ";"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
std::vector<StorageLocalSymbol> localSymbols;
|
||||
|
||||
@@ -1239,9 +1288,9 @@ std::vector<StorageLocalSymbol> SqliteStorage::getAll<StorageLocalSymbol>(const
|
||||
template <>
|
||||
std::vector<StorageSourceLocation> SqliteStorage::getAll<StorageSourceLocation>(const std::string& query) const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT id, file_node_id, start_line, start_column, end_line, end_column, type FROM source_location " + query + ";"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
std::vector<StorageSourceLocation> sourceLocations;
|
||||
|
||||
@@ -1268,9 +1317,9 @@ std::vector<StorageSourceLocation> SqliteStorage::getAll<StorageSourceLocation>(
|
||||
template <>
|
||||
std::vector<StorageOccurrence> SqliteStorage::getAll<StorageOccurrence>(const std::string& query) const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT element_id, source_location_id FROM occurrence " + query + ";"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
std::vector<StorageOccurrence> occurrences;
|
||||
|
||||
@@ -1292,9 +1341,9 @@ std::vector<StorageOccurrence> SqliteStorage::getAll<StorageOccurrence>(const st
|
||||
template <>
|
||||
std::vector<StorageComponentAccess> SqliteStorage::getAll<StorageComponentAccess>(const std::string& query) const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT id, node_id, type FROM component_access " + query + ";"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
std::vector<StorageComponentAccess> componentAccesses;
|
||||
|
||||
@@ -1317,9 +1366,9 @@ std::vector<StorageComponentAccess> SqliteStorage::getAll<StorageComponentAccess
|
||||
template <>
|
||||
std::vector<StorageCommentLocation> SqliteStorage::getAll<StorageCommentLocation>(const std::string& query) const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT id, file_node_id, start_line, start_column, end_line, end_column FROM comment_location " + query + ";"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
std::vector<StorageCommentLocation> commentLocations;
|
||||
|
||||
@@ -1347,9 +1396,9 @@ std::vector<StorageCommentLocation> SqliteStorage::getAll<StorageCommentLocation
|
||||
template <>
|
||||
std::vector<StorageError> SqliteStorage::getAll<StorageError>(const std::string& query) const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT message, fatal, indexed, file_path, line_number, column_number FROM error " + query + ";"
|
||||
).c_str());
|
||||
);
|
||||
|
||||
std::vector<StorageError> errors;
|
||||
Id id = 1;
|
||||
|
||||
@@ -142,6 +142,12 @@ private:
|
||||
void clearTables();
|
||||
void setupTables();
|
||||
|
||||
void executeStatement(const std::string& statement) const;
|
||||
void executeStatement(CppSQLite3Statement& statement) const;
|
||||
int executeScalar(const std::string& statement) const;
|
||||
CppSQLite3Query executeQuery(const std::string& statement) const;
|
||||
CppSQLite3Query executeQuery(CppSQLite3Statement& statement) const;
|
||||
|
||||
bool hasTable(const std::string& tableName) const;
|
||||
|
||||
std::string getMetaValue(const std::string& key) const;
|
||||
|
||||
@@ -34,6 +34,16 @@ add_files(
|
||||
data/parser/cxx/CommentHandler.h
|
||||
data/parser/cxx/CxxAstVisitor.cpp
|
||||
data/parser/cxx/CxxAstVisitor.h
|
||||
data/parser/cxx/CxxAstVisitorComponent.cpp
|
||||
data/parser/cxx/CxxAstVisitorComponent.h
|
||||
data/parser/cxx/CxxAstVisitorComponentContext.cpp
|
||||
data/parser/cxx/CxxAstVisitorComponentContext.h
|
||||
data/parser/cxx/CxxAstVisitorComponentDeclRefKind.cpp
|
||||
data/parser/cxx/CxxAstVisitorComponentDeclRefKind.h
|
||||
data/parser/cxx/CxxAstVisitorComponentIndexer.cpp
|
||||
data/parser/cxx/CxxAstVisitorComponentIndexer.h
|
||||
data/parser/cxx/CxxAstVisitorComponentTypeRefKind.cpp
|
||||
data/parser/cxx/CxxAstVisitorComponentTypeRefKind.h
|
||||
data/parser/cxx/CxxCompilationDatabaseSingle.cpp
|
||||
data/parser/cxx/CxxCompilationDatabaseSingle.h
|
||||
data/parser/cxx/CxxContext.cpp
|
||||
@@ -46,6 +56,8 @@ add_files(
|
||||
data/parser/cxx/CxxVerboseAstVisitor.h
|
||||
data/parser/cxx/PreprocessorCallbacks.cpp
|
||||
data/parser/cxx/PreprocessorCallbacks.h
|
||||
data/parser/cxx/utilityCxxAstVisitor.cpp
|
||||
data/parser/cxx/utilityCxxAstVisitor.h
|
||||
|
||||
utility/CompilationDatabase.cpp
|
||||
utility/CompilationDatabase.h
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,11 @@
|
||||
#ifndef CXX_AST_VISITOR_H
|
||||
#define CXX_AST_VISITOR_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include <clang/AST/RecursiveASTVisitor.h>
|
||||
|
||||
#include "data/parser/cxx/CxxContext.h"
|
||||
#include "data/parser/AccessKind.h"
|
||||
#include "data/parser/ReferenceKind.h"
|
||||
#include "data/parser/SymbolKind.h"
|
||||
#include "utility/messaging/MessageInterruptTasksCounter.h"
|
||||
#include "utility/Cache.h"
|
||||
|
||||
@@ -18,6 +13,12 @@ class ParserClient;
|
||||
struct ParseLocation;
|
||||
class FileRegister;
|
||||
|
||||
class CxxAstVisitorComponent;
|
||||
class CxxAstVisitorComponentContext;
|
||||
class CxxAstVisitorComponentDeclRefKind;
|
||||
class CxxAstVisitorComponentTypeRefKind;
|
||||
class CxxAstVisitorComponentIndexer;
|
||||
|
||||
// methods are called in this order:
|
||||
// TraverseDecl()
|
||||
// `- TraverseFunctionDecl()
|
||||
@@ -29,29 +30,18 @@ class FileRegister;
|
||||
// | `- VisitFunctionDecl()
|
||||
// `- TraverseChildNodes()
|
||||
|
||||
class ScopedContextKindSetter
|
||||
{
|
||||
public:
|
||||
ScopedContextKindSetter(const ReferenceKind refKind, std::vector<ReferenceKind>* stack)
|
||||
: m_stack(stack)
|
||||
{
|
||||
m_stack->push_back(refKind);
|
||||
}
|
||||
|
||||
~ScopedContextKindSetter()
|
||||
{
|
||||
m_stack->pop_back();
|
||||
}
|
||||
private:
|
||||
std::vector<ReferenceKind>* m_stack;
|
||||
};
|
||||
|
||||
class CxxAstVisitor: public clang::RecursiveASTVisitor<CxxAstVisitor>
|
||||
{
|
||||
public:
|
||||
CxxAstVisitor(clang::ASTContext* astContext, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister);
|
||||
virtual ~CxxAstVisitor();
|
||||
|
||||
template <typename T>
|
||||
std::shared_ptr<T> getComponent();
|
||||
|
||||
std::shared_ptr<DeclNameCache> getDeclNameCache();
|
||||
std::shared_ptr<TypeNameCache> getTypeNameCache();
|
||||
|
||||
// Indexing entry point
|
||||
void indexDecl(clang::Decl *d);
|
||||
|
||||
@@ -59,6 +49,8 @@ public:
|
||||
virtual bool shouldVisitTemplateInstantiations() const;
|
||||
virtual bool shouldVisitImplicitCode() const;
|
||||
|
||||
bool checkIgnoresTypeLoc(const clang::TypeLoc& tl) const;
|
||||
|
||||
// Traversal methods. These specify how to traverse the AST and record context info.
|
||||
virtual bool TraverseDecl(clang::Decl *d);
|
||||
virtual bool TraverseQualifiedTypeLoc(clang::QualifiedTypeLoc tl);
|
||||
@@ -66,7 +58,8 @@ public:
|
||||
virtual bool TraverseType(clang::QualType t);
|
||||
virtual bool TraverseStmt(clang::Stmt *stmt);
|
||||
|
||||
virtual bool TraverseCXXRecordDecl(clang::CXXRecordDecl *d);
|
||||
virtual bool TraverseCXXRecordDecl(clang::CXXRecordDecl* d);
|
||||
bool traverseCXXBaseSpecifier(const clang::CXXBaseSpecifier& d);
|
||||
virtual bool TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d);
|
||||
virtual bool TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d);
|
||||
virtual bool TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc loc);
|
||||
@@ -85,10 +78,27 @@ public:
|
||||
virtual bool TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* s);
|
||||
virtual bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);
|
||||
virtual bool TraverseLambdaCapture(clang::LambdaExpr* lambdaExpr, const clang::LambdaCapture* capture);
|
||||
virtual bool TraverseBinComma(clang::BinaryOperator* s);
|
||||
|
||||
#define OPERATOR(NAME) virtual bool TraverseBin##NAME##Assign(clang::CompoundAssignOperator *s) { return TraverseAssignCommon(s); }
|
||||
OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub)
|
||||
OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor)
|
||||
#undef OPERATOR
|
||||
|
||||
|
||||
void traverseDeclContextHelper(clang::DeclContext* d);
|
||||
bool TraverseCallCommon(clang::CallExpr* s);
|
||||
bool TraverseAssignCommon(clang::BinaryOperator* s);
|
||||
|
||||
// Visitor methods. These actually record stuff and store it in the database.
|
||||
virtual bool VisitCastExpr(clang::CastExpr* s);
|
||||
virtual bool VisitUnaryAddrOf(clang::UnaryOperator* s);
|
||||
virtual bool VisitUnaryDeref(clang::UnaryOperator* s);
|
||||
virtual bool VisitDeclStmt(clang::DeclStmt* s);
|
||||
virtual bool VisitReturnStmt(clang::ReturnStmt* s);
|
||||
virtual bool VisitInitListExpr(clang::InitListExpr* s);
|
||||
|
||||
|
||||
virtual bool VisitTagDecl(clang::TagDecl* d);
|
||||
virtual bool VisitClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl* d);
|
||||
virtual bool VisitFunctionDecl(clang::FunctionDecl* d);
|
||||
@@ -114,39 +124,13 @@ public:
|
||||
virtual bool VisitLambdaExpr(clang::LambdaExpr* s);
|
||||
virtual bool VisitConstructorInitializer(clang::CXXCtorInitializer* init);
|
||||
|
||||
protected:
|
||||
// General helpers
|
||||
bool isImplicit(const clang::Decl* d) const;
|
||||
bool shouldVisitDecl(const clang::Decl* decl);
|
||||
bool shouldVisitReference(const clang::SourceLocation& referenceLocation, const clang::Decl* contextDecl);
|
||||
bool isLocatedInUnparsedProjectFile(clang::SourceLocation loc);
|
||||
bool isLocatedInProjectFile(clang::SourceLocation loc);
|
||||
|
||||
ParseLocation getParseLocationOfTagDeclBody(clang::TagDecl* decl) const;
|
||||
ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const;
|
||||
ParseLocation getParseLocation(const clang::SourceLocation& loc) const;
|
||||
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
|
||||
AccessKind convertAccessSpecifier(clang::AccessSpecifier access) const;
|
||||
SymbolKind convertTagKind(clang::TagTypeKind tagKind);
|
||||
|
||||
private:
|
||||
ReferenceKind consumeDeclRefContextKind();
|
||||
SymbolKind getSymbolKind(clang::VarDecl* d);
|
||||
|
||||
typedef clang::RecursiveASTVisitor<CxxAstVisitor> base;
|
||||
|
||||
const clang::NamedDecl* getTopmostContextDecl() const;
|
||||
NameHierarchy getContextName(const size_t skip = 0) const;
|
||||
NameHierarchy getContextName(const NameHierarchy& fallback, const size_t skip = 0) const;
|
||||
bool checkIgnoresTypeLoc(const clang::TypeLoc& tl);
|
||||
|
||||
struct FileIdHash
|
||||
{
|
||||
size_t operator()(clang::FileID fileID) const
|
||||
{
|
||||
return fileID.getHashValue();
|
||||
}
|
||||
};
|
||||
typedef clang::RecursiveASTVisitor<CxxAstVisitor> Base;
|
||||
|
||||
clang::ASTContext* m_astContext;
|
||||
clang::Preprocessor* m_preprocessor;
|
||||
@@ -155,15 +139,26 @@ private:
|
||||
|
||||
MessageInterruptTasksCounter m_interruptCounter;
|
||||
|
||||
ReferenceKind m_typeRefContext;
|
||||
ReferenceKind m_declRefContext;
|
||||
std::vector<std::shared_ptr<CxxContext>> m_contextStack;
|
||||
std::shared_ptr<CxxContext> m_templateArgumentContext;
|
||||
std::vector<std::shared_ptr<CxxAstVisitorComponent>> m_components;
|
||||
std::shared_ptr<CxxAstVisitorComponentContext> m_contextComponent;
|
||||
std::shared_ptr<CxxAstVisitorComponentDeclRefKind> m_declRefKindComponent;
|
||||
std::shared_ptr<CxxAstVisitorComponentTypeRefKind> m_typeRefKindComponent;
|
||||
std::shared_ptr<CxxAstVisitorComponentIndexer> m_indexerComponent;
|
||||
|
||||
std::shared_ptr<DeclNameCache> m_declNameCache;
|
||||
std::shared_ptr<TypeNameCache> m_typeNameCache;
|
||||
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inUnparsedProjectFileMap;
|
||||
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inProjectFileMap;
|
||||
};
|
||||
|
||||
template <>
|
||||
std::shared_ptr<CxxAstVisitorComponentContext> CxxAstVisitor::getComponent();
|
||||
|
||||
template <>
|
||||
std::shared_ptr<CxxAstVisitorComponentTypeRefKind> CxxAstVisitor::getComponent();
|
||||
|
||||
template <>
|
||||
std::shared_ptr<CxxAstVisitorComponentDeclRefKind> CxxAstVisitor::getComponent();
|
||||
|
||||
template <>
|
||||
std::shared_ptr<CxxAstVisitorComponentIndexer> CxxAstVisitor::getComponent();
|
||||
|
||||
#endif // CXX_AST_VISITOR_H
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "data/parser/cxx/CxxAstVisitorComponent.h"
|
||||
|
||||
CxxAstVisitorComponent::CxxAstVisitorComponent(CxxAstVisitor* astVisitor)
|
||||
: m_astVisitor(astVisitor)
|
||||
{
|
||||
}
|
||||
|
||||
CxxAstVisitorComponent::~CxxAstVisitorComponent()
|
||||
{
|
||||
}
|
||||
|
||||
CxxAstVisitor* CxxAstVisitorComponent::getAstVisitor()
|
||||
{
|
||||
return m_astVisitor;
|
||||
}
|
||||
|
||||
const CxxAstVisitor* CxxAstVisitorComponent::getAstVisitor() const
|
||||
{
|
||||
return m_astVisitor;
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
#ifndef CXX_AST_VISITOR_COMPONENT_H
|
||||
#define CXX_AST_VISITOR_COMPONENT_H
|
||||
|
||||
#include "data/parser/cxx/CxxAstVisitor.h"
|
||||
|
||||
// CxxAstVisitorComponent: This is the base class for all ast visitor components.
|
||||
// Each component can override it's begin-/endTraverse and visit methods in order to provide some functionality. The CxxAstVisitor
|
||||
// executes all of these methods of registered components while traversing the AST.
|
||||
class CxxAstVisitorComponent
|
||||
{
|
||||
public:
|
||||
CxxAstVisitorComponent(CxxAstVisitor* astVisitor);
|
||||
virtual ~CxxAstVisitorComponent();
|
||||
|
||||
#define DEF_TRAVERSE_CUSTOM_TYPE_PTR(__NAME_TYPE__, __PARAM_TYPE__) \
|
||||
virtual void beginTraverse##__NAME_TYPE__(clang::__PARAM_TYPE__ *v) {} \
|
||||
virtual void endTraverse##__NAME_TYPE__(clang::__PARAM_TYPE__ *v) {}
|
||||
|
||||
#define DEF_TRAVERSE_CUSTOM_TYPE(__NAME_TYPE__, __PARAM_TYPE__) \
|
||||
virtual void beginTraverse##__NAME_TYPE__(clang::__PARAM_TYPE__ v) {} \
|
||||
virtual void endTraverse##__NAME_TYPE__(clang::__PARAM_TYPE__ v) {}
|
||||
|
||||
#define DEF_TRAVERSE_TYPE_PTR(__TYPE__) \
|
||||
DEF_TRAVERSE_CUSTOM_TYPE_PTR(__TYPE__, __TYPE__)
|
||||
|
||||
#define DEF_TRAVERSE_TYPE(__TYPE__) \
|
||||
DEF_TRAVERSE_CUSTOM_TYPE(__TYPE__, __TYPE__)
|
||||
|
||||
DEF_TRAVERSE_TYPE_PTR(Decl)
|
||||
|
||||
DEF_TRAVERSE_TYPE_PTR(Stmt)
|
||||
|
||||
DEF_TRAVERSE_CUSTOM_TYPE(Type, QualType)
|
||||
|
||||
DEF_TRAVERSE_TYPE(TypeLoc)
|
||||
|
||||
DEF_TRAVERSE_TYPE_PTR(FunctionDecl)
|
||||
|
||||
DEF_TRAVERSE_TYPE_PTR(ClassTemplateSpecializationDecl)
|
||||
|
||||
DEF_TRAVERSE_TYPE_PTR(ClassTemplatePartialSpecializationDecl)
|
||||
|
||||
DEF_TRAVERSE_TYPE(TemplateSpecializationTypeLoc)
|
||||
|
||||
DEF_TRAVERSE_TYPE_PTR(LambdaExpr)
|
||||
|
||||
DEF_TRAVERSE_TYPE_PTR(DeclRefExpr)
|
||||
|
||||
DEF_TRAVERSE_TYPE_PTR(UnresolvedLookupExpr)
|
||||
|
||||
virtual void beginTraverseCallCommonCallee() {}
|
||||
virtual void endTraverseCallCommonCallee() {}
|
||||
|
||||
virtual void beginTraverseCallCommonArgument() {}
|
||||
virtual void endTraverseCallCommonArgument() {}
|
||||
|
||||
virtual void beginTraverseBinCommaLhs() {}
|
||||
virtual void endTraverseBinCommaLhs() {}
|
||||
|
||||
virtual void beginTraverseBinCommaRhs() {}
|
||||
virtual void endTraverseBinCommaRhs() {}
|
||||
|
||||
virtual void beginTraverseAssignCommonLhs() {}
|
||||
virtual void endTraverseAssignCommonLhs() {}
|
||||
|
||||
virtual void beginTraverseAssignCommonRhs() {}
|
||||
virtual void endTraverseAssignCommonRhs() {}
|
||||
|
||||
virtual void beginTraverseCXXBaseSpecifier() {}
|
||||
virtual void endTraverseCXXBaseSpecifier() {}
|
||||
|
||||
virtual void beginTraverseTemplateDefaultArgumentLoc() {}
|
||||
virtual void endTraverseTemplateDefaultArgumentLoc() {}
|
||||
|
||||
DEF_TRAVERSE_CUSTOM_TYPE_PTR(ConstructorInitializer, CXXCtorInitializer)
|
||||
|
||||
DEF_TRAVERSE_TYPE_PTR(CXXTemporaryObjectExpr)
|
||||
|
||||
virtual void beginTraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc) {}
|
||||
virtual void endTraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc) {}
|
||||
|
||||
virtual void beginTraverseLambdaCapture(clang::LambdaExpr *lambdaExpr, const clang::LambdaCapture *capture) {}
|
||||
virtual void endTraverseLambdaCapture(clang::LambdaExpr *lambdaExpr, const clang::LambdaCapture *capture) {}
|
||||
|
||||
virtual void visitTagDecl(clang::TagDecl* d) {}
|
||||
virtual void visitClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl* d) {}
|
||||
virtual void visitVarDecl(clang::VarDecl* d) {}
|
||||
virtual void visitFieldDecl(clang::FieldDecl* d) {}
|
||||
virtual void visitFunctionDecl(clang::FunctionDecl* d) {}
|
||||
virtual void visitCXXMethodDecl(clang::CXXMethodDecl* d) {}
|
||||
virtual void visitEnumConstantDecl(clang::EnumConstantDecl* d) {}
|
||||
virtual void visitNamespaceDecl(clang::NamespaceDecl* d) {}
|
||||
virtual void visitNamespaceAliasDecl(clang::NamespaceAliasDecl* d) {}
|
||||
virtual void visitTypedefDecl(clang::TypedefDecl* d) {}
|
||||
virtual void visitTypeAliasDecl(clang::TypeAliasDecl* d) {}
|
||||
virtual void visitUsingDirectiveDecl(clang::UsingDirectiveDecl* d) {}
|
||||
virtual void visitUsingDecl(clang::UsingDecl* d) {}
|
||||
virtual void visitNonTypeTemplateParmDecl(clang::NonTypeTemplateParmDecl* d) {}
|
||||
virtual void visitTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d) {}
|
||||
virtual void visitTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d) {}
|
||||
|
||||
virtual void visitTypeLoc(clang::TypeLoc tl) {}
|
||||
|
||||
virtual void visitCastExpr(clang::CastExpr* s) {}
|
||||
virtual void visitUnaryAddrOf(clang::UnaryOperator* s) {}
|
||||
virtual void visitUnaryDeref(clang::UnaryOperator* s) {}
|
||||
virtual void visitDeclStmt(clang::DeclStmt* s) {}
|
||||
virtual void visitReturnStmt(clang::ReturnStmt* s) {}
|
||||
virtual void visitInitListExpr(clang::InitListExpr* s) {}
|
||||
virtual void visitDeclRefExpr(clang::DeclRefExpr* s) {}
|
||||
virtual void visitMemberExpr(clang::MemberExpr* s) {}
|
||||
virtual void visitCXXConstructExpr(clang::CXXConstructExpr* s) {}
|
||||
virtual void visitLambdaExpr(clang::LambdaExpr* s) {}
|
||||
|
||||
virtual void visitConstructorInitializer(clang::CXXCtorInitializer* init) {}
|
||||
|
||||
#undef DEF_TRAVERSE_CUSTOM_TYPE_PTR
|
||||
#undef DEF_TRAVERSE_CUSTOM_TYPE
|
||||
#undef DEF_TRAVERSE_TYPE_PTR
|
||||
#undef DEF_TRAVERSE_TYPE
|
||||
|
||||
protected:
|
||||
CxxAstVisitor* getAstVisitor();
|
||||
const CxxAstVisitor* getAstVisitor() const;
|
||||
|
||||
private:
|
||||
CxxAstVisitor* m_astVisitor;
|
||||
};
|
||||
|
||||
#endif // CXX_AST_VISITOR_COMPONENT_H
|
||||
@@ -0,0 +1,200 @@
|
||||
#include "data/parser/cxx/CxxAstVisitorComponentContext.h"
|
||||
|
||||
#include "utility/ScopedFunctor.h"
|
||||
|
||||
CxxAstVisitorComponentContext::CxxAstVisitorComponentContext(CxxAstVisitor* astVisitor)
|
||||
: CxxAstVisitorComponent(astVisitor)
|
||||
{
|
||||
}
|
||||
|
||||
CxxAstVisitorComponentContext::~CxxAstVisitorComponentContext()
|
||||
{
|
||||
}
|
||||
|
||||
const clang::NamedDecl* CxxAstVisitorComponentContext::getTopmostContextDecl() const
|
||||
{
|
||||
for (std::vector<std::shared_ptr<CxxContext>>::const_reverse_iterator it = m_contextStack.rbegin(); it != m_contextStack.rend(); it ++)
|
||||
{
|
||||
if (*it)
|
||||
{
|
||||
const clang::NamedDecl* decl = (*it)->getDecl();
|
||||
if (decl)
|
||||
{
|
||||
return decl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NameHierarchy CxxAstVisitorComponentContext::getContextName(const size_t skip)
|
||||
{
|
||||
size_t skipped = 0;
|
||||
|
||||
for (auto it = m_contextStack.rbegin(); it != m_contextStack.rend(); it++)
|
||||
{
|
||||
if (*it)
|
||||
{
|
||||
if (skipped >= skip)
|
||||
{
|
||||
return (*it)->getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
skipped++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return getAstVisitor()->getDeclNameCache()->getValue(nullptr);
|
||||
}
|
||||
|
||||
NameHierarchy CxxAstVisitorComponentContext::getContextName(const NameHierarchy& fallback, const size_t skip)
|
||||
{
|
||||
size_t skipped = 0;
|
||||
|
||||
for (auto it = m_contextStack.rbegin(); it != m_contextStack.rend(); it++)
|
||||
{
|
||||
if (*it)
|
||||
{
|
||||
if (skipped >= skip)
|
||||
{
|
||||
return (*it)->getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
skipped++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::beginTraverseDecl(clang::Decl* d)
|
||||
{
|
||||
std::shared_ptr<CxxContextDecl> context;
|
||||
|
||||
if (d &&
|
||||
clang::isa<clang::NamedDecl>(d) &&
|
||||
!clang::isa<clang::ParmVarDecl>(d) && // no parameter
|
||||
!(clang::isa<clang::VarDecl>(d) && d->getParentFunctionOrMethod() != NULL) && // no local variable
|
||||
!clang::isa<clang::UsingDirectiveDecl>(d) && // no using directive decl
|
||||
!clang::isa<clang::UsingDecl>(d) && // no using decl
|
||||
!clang::isa<clang::NamespaceDecl>(d) // no namespace
|
||||
){
|
||||
clang::NamedDecl* nd = clang::dyn_cast<clang::NamedDecl>(d);
|
||||
context = std::make_shared<CxxContextDecl>(nd, getAstVisitor()->getDeclNameCache());
|
||||
}
|
||||
|
||||
m_contextStack.push_back(context);
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::endTraverseDecl(clang::Decl* d)
|
||||
{
|
||||
m_contextStack.pop_back();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::beginTraverseTypeLoc(clang::TypeLoc tl)
|
||||
{
|
||||
std::shared_ptr<CxxContextType> context;
|
||||
|
||||
if (!getAstVisitor()->checkIgnoresTypeLoc(tl))
|
||||
{
|
||||
context = std::make_shared<CxxContextType>(tl.getTypePtr(), getAstVisitor()->getTypeNameCache());
|
||||
}
|
||||
|
||||
m_contextStack.push_back(context);
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::endTraverseTypeLoc(clang::TypeLoc tl)
|
||||
{
|
||||
m_contextStack.pop_back();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::beginTraverseLambdaExpr(clang::LambdaExpr* s)
|
||||
{
|
||||
clang::CXXMethodDecl* methodDecl = s->getCallOperator();
|
||||
m_contextStack.push_back(std::make_shared<CxxContextDecl>(methodDecl, getAstVisitor()->getDeclNameCache()));
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::endTraverseLambdaExpr(clang::LambdaExpr* s)
|
||||
{
|
||||
m_contextStack.pop_back();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::beginTraverseFunctionDecl(clang::FunctionDecl* d)
|
||||
{
|
||||
m_templateArgumentContext.push_back(std::make_shared<CxxContextDecl>(d, getAstVisitor()->getDeclNameCache()));
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::endTraverseFunctionDecl(clang::FunctionDecl* d)
|
||||
{
|
||||
m_templateArgumentContext.pop_back();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::beginTraverseClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl *d)
|
||||
{
|
||||
m_templateArgumentContext.push_back(std::make_shared<CxxContextDecl>(d, getAstVisitor()->getDeclNameCache()));
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::endTraverseClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl *d)
|
||||
{
|
||||
m_templateArgumentContext.pop_back();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::beginTraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d)
|
||||
{
|
||||
m_templateArgumentContext.push_back(std::make_shared<CxxContextDecl>(d, getAstVisitor()->getDeclNameCache()));
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::endTraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d)
|
||||
{
|
||||
m_templateArgumentContext.pop_back();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::beginTraverseDeclRefExpr(clang::DeclRefExpr* s)
|
||||
{
|
||||
m_templateArgumentContext.push_back(std::make_shared<CxxContextDecl>(s->getDecl(), getAstVisitor()->getDeclNameCache()));
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::endTraverseDeclRefExpr(clang::DeclRefExpr* s)
|
||||
{
|
||||
m_templateArgumentContext.pop_back();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::beginTraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc)
|
||||
{
|
||||
m_templateArgumentContext.push_back(std::make_shared<CxxContextType>(loc.getTypePtr(), getAstVisitor()->getTypeNameCache()));
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::endTraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc)
|
||||
{
|
||||
m_templateArgumentContext.pop_back();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::beginTraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e) // TODO: do this for unresolved and dependent stuff
|
||||
{
|
||||
std::shared_ptr<CxxContext> clear;
|
||||
m_templateArgumentContext.push_back(clear);
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::endTraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e)
|
||||
{
|
||||
m_templateArgumentContext.pop_back();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::beginTraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc)
|
||||
{
|
||||
std::shared_ptr<CxxContext> context;
|
||||
|
||||
if (!m_templateArgumentContext.empty())
|
||||
{
|
||||
context = m_templateArgumentContext.back();
|
||||
}
|
||||
|
||||
m_contextStack.push_back(context);
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentContext::endTraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc)
|
||||
{
|
||||
m_contextStack.pop_back();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef CXX_AST_VISITOR_COMPONENT_CONTEXT_H
|
||||
#define CXX_AST_VISITOR_COMPONENT_CONTEXT_H
|
||||
|
||||
#include "data/parser/cxx/CxxAstVisitorComponent.h"
|
||||
#include "data/parser/cxx/CxxContext.h"
|
||||
|
||||
// This CxxAstVisitorComponent is responsible for recording and providing the decl/type that acts as the context of the currently traversed/visited node.
|
||||
// Example: void foo() { bar(); }
|
||||
// For this snippet the declaration of "foo" serves as the context of the call to "bar"
|
||||
class CxxAstVisitorComponentContext: public CxxAstVisitorComponent
|
||||
{
|
||||
public:
|
||||
CxxAstVisitorComponentContext(CxxAstVisitor* astVisitor);
|
||||
virtual ~CxxAstVisitorComponentContext();
|
||||
|
||||
const clang::NamedDecl* getTopmostContextDecl() const;
|
||||
NameHierarchy getContextName(const size_t skip = 0);
|
||||
NameHierarchy getContextName(const NameHierarchy& fallback, const size_t skip = 0);
|
||||
|
||||
virtual void beginTraverseDecl(clang::Decl* d);
|
||||
virtual void endTraverseDecl(clang::Decl* d);
|
||||
|
||||
virtual void beginTraverseTypeLoc(clang::TypeLoc tl);
|
||||
virtual void endTraverseTypeLoc(clang::TypeLoc tl);
|
||||
|
||||
virtual void beginTraverseLambdaExpr(clang::LambdaExpr* s);
|
||||
virtual void endTraverseLambdaExpr(clang::LambdaExpr* s);
|
||||
|
||||
virtual void beginTraverseFunctionDecl(clang::FunctionDecl* d);
|
||||
virtual void endTraverseFunctionDecl(clang::FunctionDecl* d);
|
||||
|
||||
virtual void beginTraverseClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl *d);
|
||||
virtual void endTraverseClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl *d);
|
||||
|
||||
virtual void beginTraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d);
|
||||
virtual void endTraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d);
|
||||
|
||||
virtual void beginTraverseDeclRefExpr(clang::DeclRefExpr* s);
|
||||
virtual void endTraverseDeclRefExpr(clang::DeclRefExpr* s);
|
||||
|
||||
virtual void beginTraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc);
|
||||
virtual void endTraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc);
|
||||
|
||||
virtual void beginTraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e);
|
||||
virtual void endTraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e);
|
||||
|
||||
virtual void beginTraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);
|
||||
virtual void endTraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<CxxContext>> m_contextStack;
|
||||
std::vector<std::shared_ptr<CxxContext>> m_templateArgumentContext;
|
||||
};
|
||||
|
||||
#endif // CXX_AST_VISITOR_COMPONENT_CONTEXT_H
|
||||
@@ -0,0 +1,178 @@
|
||||
#include "data/parser/cxx/CxxAstVisitorComponentDeclRefKind.h"
|
||||
|
||||
CxxAstVisitorComponentDeclRefKind::CxxAstVisitorComponentDeclRefKind(CxxAstVisitor* astVisitor)
|
||||
: CxxAstVisitorComponent(astVisitor)
|
||||
, m_thisRefKind(REFERENCE_USAGE)
|
||||
, m_childRefKind(REFERENCE_USAGE)
|
||||
{
|
||||
}
|
||||
|
||||
CxxAstVisitorComponentDeclRefKind::~CxxAstVisitorComponentDeclRefKind()
|
||||
{
|
||||
}
|
||||
|
||||
ReferenceKind CxxAstVisitorComponentDeclRefKind::getReferenceKind() const
|
||||
{
|
||||
return m_thisRefKind;
|
||||
}
|
||||
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::beginTraverseDecl(clang::Decl* d)
|
||||
{
|
||||
saveAll();
|
||||
m_thisRefKind = REFERENCE_USAGE;
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::endTraverseDecl(clang::Decl* d)
|
||||
{
|
||||
restoreAll();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::beginTraverseStmt(clang::Stmt* s)
|
||||
{
|
||||
saveAll();
|
||||
|
||||
if (s == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_thisRefKind = m_childRefKind;
|
||||
if (!clang::isa<clang::Expr>(s))
|
||||
{
|
||||
m_thisRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
m_childRefKind = m_thisRefKind;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::endTraverseStmt(clang::Stmt* s)
|
||||
{
|
||||
restoreAll();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::beginTraverseType(clang::QualType t)
|
||||
{
|
||||
saveAll();
|
||||
m_thisRefKind = REFERENCE_USAGE;
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::endTraverseType(clang::QualType t)
|
||||
{
|
||||
restoreAll();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::beginTraverseTypeLoc(clang::TypeLoc tl)
|
||||
{
|
||||
saveAll();
|
||||
m_thisRefKind = REFERENCE_USAGE;
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::endTraverseTypeLoc(clang::TypeLoc tl)
|
||||
{
|
||||
restoreAll();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::beginTraverseCallCommonCallee()
|
||||
{
|
||||
m_thisRefKind = REFERENCE_CALL;
|
||||
m_childRefKind = REFERENCE_CALL;
|
||||
}
|
||||
void CxxAstVisitorComponentDeclRefKind::beginTraverseCallCommonArgument()
|
||||
{
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::beginTraverseBinCommaLhs()
|
||||
{
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::beginTraverseBinCommaRhs()
|
||||
{
|
||||
m_childRefKind = m_thisRefKind;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::beginTraverseAssignCommonLhs()
|
||||
{
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::beginTraverseAssignCommonRhs()
|
||||
{
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::beginTraverseConstructorInitializer(clang::CXXCtorInitializer* init)
|
||||
{
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::beginTraverseCXXTemporaryObjectExpr(clang::CXXTemporaryObjectExpr* s)
|
||||
{
|
||||
m_thisRefKind = REFERENCE_CALL;
|
||||
m_childRefKind = REFERENCE_CALL;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::visitVarDecl(clang::VarDecl* d)
|
||||
{
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::visitCastExpr(clang::CastExpr* s)
|
||||
{
|
||||
switch (s->getCastKind())
|
||||
{
|
||||
case clang::CK_ArrayToPointerDecay:
|
||||
case clang::CK_ToVoid:
|
||||
case clang::CK_LValueToRValue:
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::visitUnaryAddrOf(clang::UnaryOperator* s)
|
||||
{
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::visitUnaryDeref(clang::UnaryOperator* s)
|
||||
{
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::visitDeclStmt(clang::DeclStmt* s)
|
||||
{
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::visitReturnStmt(clang::ReturnStmt* s)
|
||||
{
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::visitInitListExpr(clang::InitListExpr* s)
|
||||
{
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::visitMemberExpr(clang::MemberExpr* s)
|
||||
{
|
||||
m_childRefKind = REFERENCE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::saveAll()
|
||||
{
|
||||
m_oldThisRefKinds.push_back(m_thisRefKind);
|
||||
m_oldChildRefKinds.push_back(m_childRefKind);
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentDeclRefKind::restoreAll()
|
||||
{
|
||||
m_thisRefKind = m_oldThisRefKinds.back();
|
||||
m_oldThisRefKinds.pop_back();
|
||||
|
||||
m_childRefKind = m_oldChildRefKinds.back();
|
||||
m_oldChildRefKinds.pop_back();
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#ifndef CXX_AST_VISITOR_COMPONENT_DECL_REF_KIND_H
|
||||
#define CXX_AST_VISITOR_COMPONENT_DECL_REF_KIND_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "data/parser/cxx/CxxAstVisitor.h"
|
||||
#include "data/parser/cxx/CxxAstVisitorComponent.h"
|
||||
|
||||
#include "data/parser/ReferenceKind.h"
|
||||
|
||||
// This CxxAstVisitorComponent is responsible for recording and providing the context based ReferenceKind for each reference to a declaration encountered while traversing the AST.
|
||||
// Example: void foo() { bar(); }
|
||||
// For this snippet the reference to "bar" is used in the context of a call.
|
||||
class CxxAstVisitorComponentDeclRefKind: public CxxAstVisitorComponent
|
||||
{
|
||||
public:
|
||||
CxxAstVisitorComponentDeclRefKind(CxxAstVisitor* astVisitor);
|
||||
virtual ~CxxAstVisitorComponentDeclRefKind();
|
||||
|
||||
ReferenceKind getReferenceKind() const;
|
||||
|
||||
virtual void beginTraverseDecl(clang::Decl* d);
|
||||
virtual void endTraverseDecl(clang::Decl* d);
|
||||
|
||||
virtual void beginTraverseStmt(clang::Stmt* s);
|
||||
virtual void endTraverseStmt(clang::Stmt* s);
|
||||
|
||||
virtual void beginTraverseType(clang::QualType t);
|
||||
virtual void endTraverseType(clang::QualType t);
|
||||
|
||||
virtual void beginTraverseTypeLoc(clang::TypeLoc tl);
|
||||
virtual void endTraverseTypeLoc(clang::TypeLoc tl);
|
||||
|
||||
virtual void beginTraverseCallCommonCallee();
|
||||
|
||||
virtual void beginTraverseCallCommonArgument();
|
||||
|
||||
virtual void beginTraverseBinCommaLhs();
|
||||
|
||||
virtual void beginTraverseBinCommaRhs();
|
||||
|
||||
virtual void beginTraverseAssignCommonLhs();
|
||||
|
||||
virtual void beginTraverseAssignCommonRhs();
|
||||
|
||||
virtual void beginTraverseConstructorInitializer(clang::CXXCtorInitializer* init);
|
||||
|
||||
virtual void beginTraverseCXXTemporaryObjectExpr(clang::CXXTemporaryObjectExpr* s);
|
||||
|
||||
virtual void visitVarDecl(clang::VarDecl* d);
|
||||
|
||||
virtual void visitCastExpr(clang::CastExpr* s);
|
||||
|
||||
virtual void visitUnaryAddrOf(clang::UnaryOperator* s);
|
||||
|
||||
virtual void visitUnaryDeref(clang::UnaryOperator* s);
|
||||
|
||||
virtual void visitDeclStmt(clang::DeclStmt* s);
|
||||
|
||||
virtual void visitReturnStmt(clang::ReturnStmt* s);
|
||||
|
||||
virtual void visitInitListExpr(clang::InitListExpr* s);
|
||||
|
||||
virtual void visitMemberExpr(clang::MemberExpr* s);
|
||||
|
||||
private:
|
||||
void saveAll();
|
||||
void restoreAll();
|
||||
|
||||
ReferenceKind m_thisRefKind;
|
||||
ReferenceKind m_childRefKind;
|
||||
|
||||
std::vector<ReferenceKind> m_oldThisRefKinds;
|
||||
std::vector<ReferenceKind> m_oldChildRefKinds;
|
||||
};
|
||||
|
||||
#endif // CXX_AST_VISITOR_COMPONENT_DECL_REF_KIND_H
|
||||
@@ -0,0 +1,682 @@
|
||||
#include "data/parser/cxx/CxxAstVisitorComponentIndexer.h"
|
||||
|
||||
#include <clang/AST/ASTContext.h>
|
||||
#include <clang/Basic/SourceLocation.h>
|
||||
#include <clang/Basic/SourceManager.h>
|
||||
#include <clang/Lex/Preprocessor.h>
|
||||
|
||||
#include "data/parser/cxx/CxxAstVisitorComponentContext.h"
|
||||
#include "data/parser/cxx/CxxAstVisitorComponentDeclRefKind.h"
|
||||
#include "data/parser/cxx/CxxAstVisitorComponentTypeRefKind.h"
|
||||
|
||||
#include "data/parser/cxx/utilityCxxAstVisitor.h"
|
||||
#include "data/parser/ParseLocation.h"
|
||||
#include "data/parser/ParserClient.h"
|
||||
#include "utility/file/FileRegister.h"
|
||||
|
||||
CxxAstVisitorComponentIndexer::CxxAstVisitorComponentIndexer(CxxAstVisitor* astVisitor, clang::ASTContext* astContext, ParserClient* client, FileRegister* fileRegister)
|
||||
: CxxAstVisitorComponent(astVisitor)
|
||||
, m_astContext(astContext)
|
||||
, m_client(client)
|
||||
, m_fileRegister(fileRegister)
|
||||
{
|
||||
}
|
||||
|
||||
CxxAstVisitorComponentIndexer::~CxxAstVisitorComponentIndexer()
|
||||
{
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::beginTraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc)
|
||||
{
|
||||
if (
|
||||
(loc.getArgument().getKind() == clang::TemplateArgument::Template) &&
|
||||
(shouldVisitReference(loc.getLocation(), getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getTopmostContextDecl()))
|
||||
){
|
||||
// TODO: maybe move this to VisitTemplateName
|
||||
m_client->recordReference(
|
||||
getAstVisitor()->getComponent<CxxAstVisitorComponentTypeRefKind>()->getReferenceKind(),
|
||||
getAstVisitor()->getDeclNameCache()->getValue(loc.getArgument().getAsTemplate().getAsTemplateDecl()),
|
||||
getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getContextName(),
|
||||
getParseLocation(loc.getLocation())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::beginTraverseLambdaCapture(clang::LambdaExpr *lambdaExpr, const clang::LambdaCapture *capture)
|
||||
{
|
||||
if ((!lambdaExpr->isInitCapture(capture)) && (capture->capturesVariable()))
|
||||
{
|
||||
clang::VarDecl* d = capture->getCapturedVar();
|
||||
SymbolKind symbolKind = getSymbolKind(d);
|
||||
if (symbolKind == SYMBOL_LOCAL_VARIABLE || symbolKind == SYMBOL_PARAMETER)
|
||||
{
|
||||
if (!d->getNameAsString().empty()) // don't record anonymous parameters
|
||||
{
|
||||
ParseLocation declLocation = getParseLocation(d->getLocation());
|
||||
std::string name =
|
||||
declLocation.filePath.fileName() + "<" +
|
||||
std::to_string(declLocation.startLineNumber) + ":" +
|
||||
std::to_string(declLocation.startColumnNumber) + ">";
|
||||
m_client->onLocalSymbolParsed(name, getParseLocation(capture->getLocation()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitTagDecl(clang::TagDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
utility::convertTagKind(d->getTagKind()),
|
||||
getParseLocation(d->getLocation()),
|
||||
getParseLocationOfTagDeclBody(d),
|
||||
utility::convertAccessSpecifier(d->getAccess()),
|
||||
utility::isImplicit(d)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
clang::NamedDecl* specializedFromDecl;
|
||||
|
||||
// todo: use context and childcontext!!
|
||||
llvm::PointerUnion<clang::ClassTemplateDecl*, clang::ClassTemplatePartialSpecializationDecl*> pu = d->getSpecializedTemplateOrPartial();
|
||||
if (pu.is<clang::ClassTemplateDecl*>())
|
||||
{
|
||||
specializedFromDecl = pu.get<clang::ClassTemplateDecl*>();
|
||||
}
|
||||
else if (pu.is<clang::ClassTemplatePartialSpecializationDecl*>())
|
||||
{
|
||||
specializedFromDecl = pu.get<clang::ClassTemplatePartialSpecializationDecl*>();
|
||||
}
|
||||
|
||||
m_client->recordReference(
|
||||
REFERENCE_TEMPLATE_SPECIALIZATION_OF, // TODO: call this REFERENCE_TEMPLATE_SPECIALIZATION and reverse the following arguments
|
||||
getAstVisitor()->getDeclNameCache()->getValue(specializedFromDecl),
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
getParseLocation(d->getLocation())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitVarDecl(clang::VarDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
SymbolKind symbolKind = getSymbolKind(d);
|
||||
if (symbolKind == SYMBOL_LOCAL_VARIABLE || symbolKind == SYMBOL_PARAMETER)
|
||||
{
|
||||
if (!d->getNameAsString().empty()) // don't record anonymous parameters
|
||||
{
|
||||
ParseLocation declLocation = getParseLocation(d->getLocation());
|
||||
std::string name =
|
||||
declLocation.filePath.fileName() + "<" +
|
||||
std::to_string(declLocation.startLineNumber) + ":" +
|
||||
std::to_string(declLocation.startColumnNumber) + ">";
|
||||
m_client->onLocalSymbolParsed(name, getParseLocation(d->getLocation()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
symbolKind,
|
||||
getParseLocation(d->getLocation()),
|
||||
utility::convertAccessSpecifier(d->getAccess()),
|
||||
utility::isImplicit(d)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitFieldDecl(clang::FieldDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
SYMBOL_FIELD,
|
||||
getParseLocation(d->getLocation()),
|
||||
utility::convertAccessSpecifier(d->getAccess()),
|
||||
utility::isImplicit(d)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitFunctionDecl(clang::FunctionDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
clang::isa<clang::CXXMethodDecl>(d) ? SYMBOL_METHOD : SYMBOL_FUNCTION,
|
||||
getParseLocation(d->getLocation()),
|
||||
getParseLocationOfFunctionBody(d),
|
||||
utility::convertAccessSpecifier(d->getAccess()),
|
||||
utility::isImplicit(d)
|
||||
);
|
||||
|
||||
if (d->isFunctionTemplateSpecialization())
|
||||
{
|
||||
m_client->recordReference(
|
||||
REFERENCE_TEMPLATE_SPECIALIZATION_OF, // TODO: call this REFERENCE_TEMPLATE_SPECIALIZATION and reverse the following arguments
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d->getPrimaryTemplate()->getTemplatedDecl()), // todo: use context and childcontext!!
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
getParseLocation(d->getLocation())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitCXXMethodDecl(clang::CXXMethodDecl* d)
|
||||
{
|
||||
// Decl has been recorded in VisitFunctionDecl
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
for (clang::CXXMethodDecl::method_iterator it = d->begin_overridden_methods(); // TODO: iterate in traversal and use RT_Overridden or so..
|
||||
it != d->end_overridden_methods(); it++)
|
||||
{
|
||||
m_client->recordReference(
|
||||
REFERENCE_OVERRIDE,
|
||||
getAstVisitor()->getDeclNameCache()->getValue(*it),
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
getParseLocation(d->getLocation())
|
||||
);
|
||||
}
|
||||
|
||||
clang::MemberSpecializationInfo* memberSpecializationInfo = d->getMemberSpecializationInfo();
|
||||
if (memberSpecializationInfo)
|
||||
{
|
||||
clang::NamedDecl* specializedNamedDecl = memberSpecializationInfo->getInstantiatedFrom();
|
||||
if (clang::isa<clang::FunctionDecl>(specializedNamedDecl))
|
||||
{
|
||||
m_client->recordReference(
|
||||
REFERENCE_TEMPLATE_MEMBER_SPECIALIZATION_OF,
|
||||
getAstVisitor()->getDeclNameCache()->getValue(specializedNamedDecl),
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
getParseLocation(d->getLocation())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitEnumConstantDecl(clang::EnumConstantDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
SYMBOL_ENUM_CONSTANT,
|
||||
getParseLocation(d->getLocation()),
|
||||
ACCESS_NONE,
|
||||
utility::isImplicit(d)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitNamespaceDecl(clang::NamespaceDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
SYMBOL_NAMESPACE,
|
||||
d->isAnonymousNamespace() ? ParseLocation() : getParseLocation(d->getLocation()),
|
||||
getParseLocation(d->getSourceRange()),
|
||||
utility::convertAccessSpecifier(d->getAccess()),
|
||||
utility::isImplicit(d)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitNamespaceAliasDecl(clang::NamespaceAliasDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
SYMBOL_NAMESPACE,
|
||||
getParseLocation(d->getLocation()),
|
||||
utility::convertAccessSpecifier(d->getAccess()),
|
||||
utility::isImplicit(d)
|
||||
);
|
||||
|
||||
m_client->recordReference(
|
||||
REFERENCE_USAGE,
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d->getAliasedNamespace()),
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
getParseLocation(d->getTargetNameLoc())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitTypedefDecl(clang::TypedefDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
SYMBOL_TYPEDEF,
|
||||
getParseLocation(d->getLocation()),
|
||||
utility::convertAccessSpecifier(d->getAccess()),
|
||||
utility::isImplicit(d)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitTypeAliasDecl(clang::TypeAliasDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
SYMBOL_TYPEDEF,
|
||||
getParseLocation(d->getLocation()),
|
||||
utility::convertAccessSpecifier(d->getAccess()),
|
||||
utility::isImplicit(d)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitUsingDirectiveDecl(clang::UsingDirectiveDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
ParseLocation loc = getParseLocation(d->getLocation());
|
||||
m_client->recordReference(
|
||||
REFERENCE_USAGE,
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d->getNominatedNamespaceAsWritten()),
|
||||
getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getContextName(NameHierarchy(loc.filePath.fileName())),
|
||||
loc
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitUsingDecl(clang::UsingDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
ParseLocation loc = getParseLocation(d->getLocation());
|
||||
m_client->recordReference(
|
||||
REFERENCE_USAGE,
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getContextName(NameHierarchy(loc.filePath.fileName())),
|
||||
loc
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitNonTypeTemplateParmDecl(clang::NonTypeTemplateParmDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d) && !d->getName().empty()) // We don't create symbols for unnamed template parameters.
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
SYMBOL_TEMPLATE_PARAMETER,
|
||||
getParseLocation(d->getLocation()),
|
||||
ACCESS_TEMPLATE_PARAMETER,
|
||||
utility::isImplicit(d)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d) && !d->getName().empty()) // We don't create symbols for unnamed template parameters.
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
SYMBOL_TEMPLATE_PARAMETER,
|
||||
getParseLocation(d->getLocation()),
|
||||
ACCESS_TEMPLATE_PARAMETER,
|
||||
utility::isImplicit(d)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d) && !d->getName().empty()) // We don't create symbols for unnamed template parameters.
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(d),
|
||||
SYMBOL_TEMPLATE_PARAMETER,
|
||||
getParseLocation(d->getLocation()),
|
||||
ACCESS_TEMPLATE_PARAMETER,
|
||||
utility::isImplicit(d)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitTypeLoc(clang::TypeLoc tl)
|
||||
{
|
||||
if ((shouldVisitReference(tl.getBeginLoc(), getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getTopmostContextDecl())) &&
|
||||
(!getAstVisitor()->checkIgnoresTypeLoc(tl)))
|
||||
{
|
||||
clang::SourceLocation loc;
|
||||
if (!tl.getAs<clang::DependentNameTypeLoc>().isNull())
|
||||
{
|
||||
const clang::DependentNameTypeLoc& dntl = tl.castAs<clang::DependentNameTypeLoc>();
|
||||
loc = dntl.getNameLoc();
|
||||
}
|
||||
else
|
||||
{
|
||||
loc = tl.getBeginLoc();
|
||||
}
|
||||
|
||||
m_client->recordReference(
|
||||
getAstVisitor()->getComponent<CxxAstVisitorComponentTypeRefKind>()->getReferenceKind(),
|
||||
getAstVisitor()->getTypeNameCache()->getValue(tl.getTypePtr()),
|
||||
getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getContextName(1), // we skip the last element because it refers to this typeloc.
|
||||
getParseLocation(loc)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitDeclRefExpr(clang::DeclRefExpr* s)
|
||||
{
|
||||
clang::ValueDecl* decl = s->getDecl();
|
||||
if (shouldVisitReference(s->getLocation(), getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getTopmostContextDecl()))
|
||||
{
|
||||
if ((clang::isa<clang::ParmVarDecl>(decl)) ||
|
||||
(clang::isa<clang::VarDecl>(decl) && decl->getParentFunctionOrMethod() != NULL)
|
||||
) {
|
||||
ParseLocation declLocation = getParseLocation(decl->getLocation());
|
||||
std::string name = declLocation.filePath.fileName() + "<" +
|
||||
std::to_string(declLocation.startLineNumber) + ":" +
|
||||
std::to_string(declLocation.startColumnNumber) + ">";
|
||||
|
||||
m_client->onLocalSymbolParsed(name, getParseLocation(s->getLocation()));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->recordReference(
|
||||
consumeDeclRefContextKind(),
|
||||
getAstVisitor()->getDeclNameCache()->getValue(s->getDecl()),
|
||||
getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getContextName(),
|
||||
getParseLocation(s->getLocation())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitMemberExpr(clang::MemberExpr* s)
|
||||
{
|
||||
if (shouldVisitReference(s->getMemberLoc(), getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getTopmostContextDecl()))
|
||||
{
|
||||
m_client->recordReference(
|
||||
consumeDeclRefContextKind(),
|
||||
getAstVisitor()->getDeclNameCache()->getValue(s->getMemberDecl()),
|
||||
getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getContextName(),
|
||||
getParseLocation(s->getMemberLoc())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitCXXConstructExpr(clang::CXXConstructExpr* s)
|
||||
{
|
||||
if (shouldVisitReference(s->getLocation(), getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getTopmostContextDecl()))
|
||||
{
|
||||
//if (e->getParenOrBraceRange().isValid()) {
|
||||
// // XXX: This code is a kludge. Recording calls to constructors is
|
||||
// // troublesome because there isn't an obvious location to associate the
|
||||
// // call with. Consider:
|
||||
// // A::A() : field(1, 2, 3) {}
|
||||
// // new A<B>(1, 2, 3)
|
||||
// // struct A { A(B); }; A f() { B b; return b; }
|
||||
// // Implicit calls to conversion operator methods pose a similar
|
||||
// // problem.
|
||||
// //
|
||||
// // Recording constructor calls is very useful, though, so, as a
|
||||
// // temporary measure, when there are constructor arguments surrounded
|
||||
// // by parentheses, associate the call with the right parenthesis.
|
||||
// //
|
||||
// // Perhaps the right fix is to associate the call with the line itself
|
||||
// // or with a larger span which may have other references nested within
|
||||
// // it. The fix may have implications for the navigator GUI.
|
||||
// RecordDeclRefExpr(
|
||||
// e->getConstructor(),
|
||||
// e->getParenOrBraceRange().getEnd(),
|
||||
// e,
|
||||
// CF_Called);
|
||||
//}
|
||||
clang::SourceLocation loc;
|
||||
clang::SourceLocation braceBeginLoc = s->getParenOrBraceRange().getBegin();
|
||||
clang::SourceLocation nameBeginLoc = s->getSourceRange().getBegin();
|
||||
if (braceBeginLoc.isValid())
|
||||
{
|
||||
if (braceBeginLoc == nameBeginLoc)
|
||||
{
|
||||
loc = nameBeginLoc;
|
||||
}
|
||||
else
|
||||
{
|
||||
loc = braceBeginLoc.getLocWithOffset(-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
loc = s->getSourceRange().getEnd();
|
||||
}
|
||||
loc = clang::Lexer::GetBeginningOfToken(loc, m_astContext->getSourceManager(), m_astContext->getLangOpts());
|
||||
|
||||
m_client->recordReference(
|
||||
consumeDeclRefContextKind(),
|
||||
getAstVisitor()->getDeclNameCache()->getValue(s->getConstructor()),
|
||||
getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getContextName(),
|
||||
getParseLocation(loc)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitLambdaExpr(clang::LambdaExpr* s)
|
||||
{
|
||||
clang::CXXMethodDecl* methodDecl = s->getCallOperator();
|
||||
if (shouldVisitDecl(methodDecl))
|
||||
{
|
||||
m_client->recordSymbol(
|
||||
getAstVisitor()->getDeclNameCache()->getValue(methodDecl),
|
||||
SYMBOL_FUNCTION,
|
||||
getParseLocation(s->getLocStart()),
|
||||
getParseLocationOfFunctionBody(methodDecl),
|
||||
ACCESS_NONE, // TODO: introduce AccessLambda
|
||||
utility::isImplicit(methodDecl)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentIndexer::visitConstructorInitializer(clang::CXXCtorInitializer* init)
|
||||
{
|
||||
if (shouldVisitReference(init->getMemberLocation(), getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getTopmostContextDecl()))
|
||||
{
|
||||
// record the field usage here because it is not a DeclRefExpr
|
||||
if (clang::FieldDecl* memberDecl = init->getMember())
|
||||
{
|
||||
m_client->recordReference(
|
||||
REFERENCE_USAGE,
|
||||
getAstVisitor()->getDeclNameCache()->getValue(memberDecl),
|
||||
getAstVisitor()->getComponent<CxxAstVisitorComponentContext>()->getContextName(),
|
||||
getParseLocation(init->getMemberLocation())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParseLocation CxxAstVisitorComponentIndexer::getParseLocationOfTagDeclBody(clang::TagDecl* decl) const
|
||||
{
|
||||
return getAstVisitor()->getParseLocationOfTagDeclBody(decl);
|
||||
}
|
||||
|
||||
ParseLocation CxxAstVisitorComponentIndexer::getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const
|
||||
{
|
||||
return getAstVisitor()->getParseLocationOfFunctionBody(decl);
|
||||
}
|
||||
|
||||
ParseLocation CxxAstVisitorComponentIndexer::getParseLocation(const clang::SourceLocation& loc) const
|
||||
{
|
||||
return getAstVisitor()->getParseLocation(loc);
|
||||
}
|
||||
|
||||
ParseLocation CxxAstVisitorComponentIndexer::getParseLocation(const clang::SourceRange& sourceRange) const
|
||||
{
|
||||
return getAstVisitor()->getParseLocation(sourceRange);
|
||||
}
|
||||
|
||||
ReferenceKind CxxAstVisitorComponentIndexer::consumeDeclRefContextKind()
|
||||
{
|
||||
ReferenceKind refKind = REFERENCE_UNDEFINED;
|
||||
|
||||
std::shared_ptr<CxxAstVisitorComponentTypeRefKind> typeRefKindComponent = getAstVisitor()->getComponent<CxxAstVisitorComponentTypeRefKind>();
|
||||
|
||||
if (typeRefKindComponent->getReferenceKind() == REFERENCE_TYPE_USAGE)
|
||||
{
|
||||
refKind = getAstVisitor()->getComponent<CxxAstVisitorComponentDeclRefKind>()->getReferenceKind();
|
||||
}
|
||||
else
|
||||
{
|
||||
refKind = typeRefKindComponent->getReferenceKind();
|
||||
}
|
||||
return refKind;
|
||||
}
|
||||
|
||||
SymbolKind CxxAstVisitorComponentIndexer::getSymbolKind(clang::VarDecl* d)
|
||||
{
|
||||
SymbolKind symbolKind = SYMBOL_KIND_MAX;
|
||||
|
||||
if (llvm::isa<clang::ParmVarDecl>(d))
|
||||
{
|
||||
symbolKind = SYMBOL_PARAMETER;
|
||||
}
|
||||
else if (d->getParentFunctionOrMethod() == NULL)
|
||||
{
|
||||
if (d->getAccess() == clang::AS_none)
|
||||
{
|
||||
symbolKind = SYMBOL_GLOBAL_VARIABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
symbolKind = SYMBOL_FIELD;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
symbolKind = SYMBOL_LOCAL_VARIABLE;
|
||||
}
|
||||
|
||||
return symbolKind;
|
||||
}
|
||||
|
||||
bool CxxAstVisitorComponentIndexer::shouldVisitDecl(const clang::Decl* decl)
|
||||
{
|
||||
if (decl)
|
||||
{
|
||||
clang::SourceLocation loc = decl->getLocation();
|
||||
bool declIsImplicit = utility::isImplicit(decl);
|
||||
if ((declIsImplicit && isLocatedInProjectFile(loc)) ||
|
||||
(!declIsImplicit && isLocatedInUnparsedProjectFile(loc)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CxxAstVisitorComponentIndexer::shouldVisitReference(const clang::SourceLocation& referenceLocation, const clang::Decl* contextDecl)
|
||||
{
|
||||
bool declIsImplicit = true; // default value is "true" to make sure that everything that should be visited gets visited.
|
||||
if (contextDecl)
|
||||
{
|
||||
declIsImplicit = utility::isImplicit(contextDecl);
|
||||
}
|
||||
|
||||
if ((declIsImplicit && isLocatedInProjectFile(referenceLocation)) ||
|
||||
(!declIsImplicit && isLocatedInUnparsedProjectFile(referenceLocation)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CxxAstVisitorComponentIndexer::isLocatedInUnparsedProjectFile(clang::SourceLocation loc)
|
||||
{
|
||||
clang::SourceManager& sourceManager = m_astContext->getSourceManager();
|
||||
clang::SourceLocation spellingLoc = sourceManager.getSpellingLoc(loc);
|
||||
|
||||
clang::FileID fileId;
|
||||
|
||||
if (spellingLoc.isValid())
|
||||
{
|
||||
fileId = sourceManager.getFileID(spellingLoc);
|
||||
}
|
||||
if (fileId.isValid())
|
||||
{
|
||||
auto it = m_inUnparsedProjectFileMap.find(fileId);
|
||||
if (it != m_inUnparsedProjectFileMap.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
if (sourceManager.isWrittenInMainFile(spellingLoc))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId);
|
||||
if (fileEntry != NULL)
|
||||
{
|
||||
std::string fileName = fileEntry->getName();
|
||||
FilePath filePath = FilePath(fileName).canonical();
|
||||
|
||||
if (m_fileRegister->hasIncludeFile(filePath))
|
||||
{
|
||||
ret = !(m_fileRegister->includeFileIsParsed(filePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
m_inUnparsedProjectFileMap[fileId] = ret;
|
||||
return ret;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CxxAstVisitorComponentIndexer::isLocatedInProjectFile(clang::SourceLocation loc)
|
||||
{
|
||||
clang::SourceManager& sourceManager = m_astContext->getSourceManager();
|
||||
clang::SourceLocation spellingLoc = sourceManager.getSpellingLoc(loc);
|
||||
|
||||
clang::FileID fileId;
|
||||
|
||||
if (spellingLoc.isValid())
|
||||
{
|
||||
fileId = sourceManager.getFileID(spellingLoc);
|
||||
}
|
||||
|
||||
if (!fileId.isInvalid())
|
||||
{
|
||||
auto it = m_inProjectFileMap.find(fileId);
|
||||
if (it != m_inProjectFileMap.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId);
|
||||
if (fileEntry != NULL)
|
||||
{
|
||||
std::string fileName = fileEntry->getName();
|
||||
FilePath filePath = FilePath(fileName).canonical();
|
||||
bool ret = m_fileRegister->hasFilePath(filePath.str());
|
||||
m_inProjectFileMap[fileId] = ret;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#ifndef CXX_AST_VISITOR_COMPONENT_INDEXER_H
|
||||
#define CXX_AST_VISITOR_COMPONENT_INDEXER_H
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "data/parser/cxx/CxxAstVisitor.h"
|
||||
#include "data/parser/cxx/CxxAstVisitorComponent.h"
|
||||
#include "data/parser/ReferenceKind.h"
|
||||
#include "data/parser/SymbolKind.h"
|
||||
|
||||
// This CxxAstVisitorComponent is responsible for recording all symbols and relations throughout the visited AST.
|
||||
class CxxAstVisitorComponentIndexer: public CxxAstVisitorComponent
|
||||
{
|
||||
public:
|
||||
CxxAstVisitorComponentIndexer(CxxAstVisitor* astVisitor, clang::ASTContext* astContext, ParserClient* client, FileRegister* fileRegister);
|
||||
virtual ~CxxAstVisitorComponentIndexer();
|
||||
|
||||
virtual void beginTraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);
|
||||
virtual void beginTraverseLambdaCapture(clang::LambdaExpr *lambdaExpr, const clang::LambdaCapture *capture);
|
||||
|
||||
virtual void visitTagDecl(clang::TagDecl* d);
|
||||
virtual void visitClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl* d);
|
||||
virtual void visitVarDecl(clang::VarDecl* d);
|
||||
virtual void visitFieldDecl(clang::FieldDecl* d);
|
||||
virtual void visitFunctionDecl(clang::FunctionDecl* d);
|
||||
virtual void visitCXXMethodDecl(clang::CXXMethodDecl* d);
|
||||
virtual void visitEnumConstantDecl(clang::EnumConstantDecl* d);
|
||||
virtual void visitNamespaceDecl(clang::NamespaceDecl* d);
|
||||
virtual void visitNamespaceAliasDecl(clang::NamespaceAliasDecl* d);
|
||||
virtual void visitTypedefDecl(clang::TypedefDecl* d);
|
||||
virtual void visitTypeAliasDecl(clang::TypeAliasDecl* d);
|
||||
virtual void visitUsingDirectiveDecl(clang::UsingDirectiveDecl* d);
|
||||
virtual void visitUsingDecl(clang::UsingDecl* d);
|
||||
virtual void visitNonTypeTemplateParmDecl(clang::NonTypeTemplateParmDecl* d);
|
||||
virtual void visitTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d);
|
||||
virtual void visitTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d);
|
||||
|
||||
virtual void visitTypeLoc(clang::TypeLoc tl);
|
||||
|
||||
virtual void visitDeclRefExpr(clang::DeclRefExpr* s);
|
||||
virtual void visitMemberExpr(clang::MemberExpr* s);
|
||||
virtual void visitCXXConstructExpr(clang::CXXConstructExpr* s);
|
||||
virtual void visitLambdaExpr(clang::LambdaExpr* s);
|
||||
|
||||
virtual void visitConstructorInitializer(clang::CXXCtorInitializer* init);
|
||||
|
||||
private:
|
||||
struct FileIdHash
|
||||
{
|
||||
size_t operator()(clang::FileID fileID) const
|
||||
{
|
||||
return fileID.getHashValue();
|
||||
}
|
||||
};
|
||||
|
||||
ParseLocation getParseLocationOfTagDeclBody(clang::TagDecl* decl) const;
|
||||
ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const;
|
||||
ParseLocation getParseLocation(const clang::SourceLocation& loc) const;
|
||||
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
|
||||
|
||||
ReferenceKind consumeDeclRefContextKind();
|
||||
SymbolKind getSymbolKind(clang::VarDecl* d);
|
||||
|
||||
bool shouldVisitDecl(const clang::Decl* decl);
|
||||
bool shouldVisitReference(const clang::SourceLocation& referenceLocation, const clang::Decl* contextDecl);
|
||||
bool isLocatedInUnparsedProjectFile(clang::SourceLocation loc);
|
||||
bool isLocatedInProjectFile(clang::SourceLocation loc);
|
||||
|
||||
clang::ASTContext* m_astContext;
|
||||
ParserClient* m_client;
|
||||
FileRegister* m_fileRegister;
|
||||
|
||||
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inUnparsedProjectFileMap;
|
||||
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inProjectFileMap;
|
||||
};
|
||||
|
||||
#endif // CXX_AST_VISITOR_COMPONENT_INDEXER_H
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "data/parser/cxx/CxxAstVisitorComponentTypeRefKind.h"
|
||||
|
||||
CxxAstVisitorComponentTypeRefKind::CxxAstVisitorComponentTypeRefKind(CxxAstVisitor* astVisitor)
|
||||
: CxxAstVisitorComponent(astVisitor)
|
||||
{
|
||||
}
|
||||
|
||||
CxxAstVisitorComponentTypeRefKind::~CxxAstVisitorComponentTypeRefKind()
|
||||
{
|
||||
}
|
||||
|
||||
ReferenceKind CxxAstVisitorComponentTypeRefKind::getReferenceKind() const
|
||||
{
|
||||
for (auto it = m_refKindStack.rbegin(); it != m_refKindStack.rend(); it++)
|
||||
{
|
||||
if ((*it) != REFERENCE_UNDEFINED)
|
||||
{
|
||||
return (*it);
|
||||
}
|
||||
}
|
||||
return REFERENCE_TYPE_USAGE;
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentTypeRefKind::beginTraverseCXXBaseSpecifier()
|
||||
{
|
||||
m_refKindStack.push_back(REFERENCE_INHERITANCE);
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentTypeRefKind::endTraverseCXXBaseSpecifier()
|
||||
{
|
||||
m_refKindStack.pop_back();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentTypeRefKind::beginTraverseTemplateDefaultArgumentLoc()
|
||||
{
|
||||
m_refKindStack.push_back(REFERENCE_TEMPLATE_DEFAULT_ARGUMENT);
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentTypeRefKind::endTraverseTemplateDefaultArgumentLoc()
|
||||
{
|
||||
m_refKindStack.pop_back();
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentTypeRefKind::beginTraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc)
|
||||
{
|
||||
if (getReferenceKind() != REFERENCE_TEMPLATE_DEFAULT_ARGUMENT)
|
||||
{
|
||||
m_refKindStack.push_back(REFERENCE_TEMPLATE_ARGUMENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_refKindStack.push_back(REFERENCE_UNDEFINED);
|
||||
}
|
||||
}
|
||||
|
||||
void CxxAstVisitorComponentTypeRefKind::endTraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc)
|
||||
{
|
||||
m_refKindStack.pop_back();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef CXX_AST_VISITOR_COMPONENT_TYPE_REF_KIND_H
|
||||
#define CXX_AST_VISITOR_COMPONENT_TYPE_REF_KIND_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "data/parser/cxx/CxxAstVisitor.h"
|
||||
#include "data/parser/cxx/CxxAstVisitorComponent.h"
|
||||
|
||||
#include "data/parser/ReferenceKind.h"
|
||||
|
||||
// This CxxAstVisitorComponent is responsible for recording and providing the context based ReferenceKind for each reference to a type encountered while traversing the AST.
|
||||
// Example: class Foo: public Bar {};
|
||||
// For this snippet the type "Bar" is used in the context of an inheritence.
|
||||
class CxxAstVisitorComponentTypeRefKind: public CxxAstVisitorComponent
|
||||
{
|
||||
public:
|
||||
CxxAstVisitorComponentTypeRefKind(CxxAstVisitor* astVisitor);
|
||||
virtual ~CxxAstVisitorComponentTypeRefKind();
|
||||
|
||||
ReferenceKind getReferenceKind() const;
|
||||
|
||||
virtual void beginTraverseCXXBaseSpecifier();
|
||||
virtual void endTraverseCXXBaseSpecifier();
|
||||
|
||||
virtual void beginTraverseTemplateDefaultArgumentLoc();
|
||||
virtual void endTraverseTemplateDefaultArgumentLoc();
|
||||
|
||||
virtual void beginTraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);
|
||||
virtual void endTraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);
|
||||
|
||||
private:
|
||||
std::vector<ReferenceKind> m_refKindStack;
|
||||
};
|
||||
|
||||
#endif // CXX_AST_VISITOR_COMPONENT_TYPE_REF_KIND_H
|
||||
@@ -0,0 +1,73 @@
|
||||
#include "data/parser/cxx/utilityCxxAstVisitor.h"
|
||||
|
||||
#include <clang/AST/DeclCXX.h>
|
||||
#include <clang/AST/DeclTemplate.h>
|
||||
|
||||
|
||||
bool utility::isImplicit(const clang::Decl* d)
|
||||
{
|
||||
if (!d)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d->isImplicit())
|
||||
{
|
||||
if (const clang::RecordDecl* rd = clang::dyn_cast_or_null<clang::RecordDecl>(d))
|
||||
{
|
||||
if (rd->isLambda())
|
||||
{
|
||||
return isImplicit(clang::dyn_cast_or_null<clang::Decl>(d->getDeclContext()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (const clang::ClassTemplateSpecializationDecl* ctsd = clang::dyn_cast_or_null<clang::ClassTemplateSpecializationDecl>(d))
|
||||
{
|
||||
if (!ctsd->isExplicitSpecialization())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (const clang::FunctionDecl* fd = clang::dyn_cast_or_null<clang::FunctionDecl>(d))
|
||||
{
|
||||
if (fd->isTemplateInstantiation() && fd->getTemplateSpecializationKind() != clang::TSK_ExplicitSpecialization) // or undefined??
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return isImplicit(clang::dyn_cast_or_null<clang::Decl>(d->getDeclContext()));
|
||||
}
|
||||
|
||||
AccessKind utility::convertAccessSpecifier(clang::AccessSpecifier access)
|
||||
{
|
||||
switch (access)
|
||||
{
|
||||
case clang::AS_public:
|
||||
return ACCESS_PUBLIC;
|
||||
case clang::AS_protected:
|
||||
return ACCESS_PROTECTED;
|
||||
case clang::AS_private:
|
||||
return ACCESS_PRIVATE;
|
||||
case clang::AS_none:
|
||||
return ACCESS_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
SymbolKind utility::convertTagKind(clang::TagTypeKind tagKind)
|
||||
{
|
||||
switch (tagKind)
|
||||
{
|
||||
case clang::TTK_Struct:
|
||||
return SYMBOL_STRUCT;
|
||||
case clang::TTK_Union:
|
||||
return SYMBOL_UNION;
|
||||
case clang::TTK_Class:
|
||||
return SYMBOL_CLASS;
|
||||
case clang::TTK_Enum:
|
||||
return SYMBOL_ENUM;
|
||||
case clang::TTK_Interface:
|
||||
return SYMBOL_KIND_MAX;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef UTILITY_CXX_AST_VISITOR_H
|
||||
#define UTILITY_CXX_AST_VISITOR_H
|
||||
|
||||
#include <clang/AST/Decl.h>
|
||||
|
||||
#include "data/parser/AccessKind.h"
|
||||
#include "data/parser/SymbolKind.h"
|
||||
|
||||
namespace utility
|
||||
{
|
||||
bool isImplicit(const clang::Decl* d);
|
||||
AccessKind convertAccessSpecifier(clang::AccessSpecifier access);
|
||||
SymbolKind convertTagKind(clang::TagTypeKind tagKind);
|
||||
}
|
||||
|
||||
#endif // UTILITY_CXX_AST_VISITOR_H
|
||||
@@ -3211,7 +3211,7 @@ public:
|
||||
));
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_argument_of_unresolved_lookup_expression_as_type_use()
|
||||
void test_cxx_parser_finds_template_argument_of_unresolved_lookup_expression()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
@@ -3227,7 +3227,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->typeUses, "void dispatch<typename MessageType>() -> dispatch<typename MessageType>::MessageType <9:4 9:14>"
|
||||
client->templateArgumentTypes, "void dispatch<typename MessageType>() -> dispatch<typename MessageType>::MessageType <9:4 9:14>"
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user