data: saving errors to Storage
* saving errors in separate sqlite table * use MessageShowErrors to show the errors in the UI * show error count permanently in the right side of the status bar with click to show * fixed clicking of error locations * fixed expanding of files with errors
This commit is contained in:
@@ -164,6 +164,35 @@ Id SqliteStorage::addSignature(Id nodeId, const std::string& signature)
|
||||
return m_database.lastRowId();
|
||||
}
|
||||
|
||||
Id SqliteStorage::addError(const std::string& message, const std::string& filePath, uint lineNumber, uint columnNumber)
|
||||
{
|
||||
std::string sanitizedMessage = utility::replace(message, "'", "''");
|
||||
|
||||
// check for duplicate
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
"SELECT * FROM error WHERE "
|
||||
"message == '" + sanitizedMessage + "' AND "
|
||||
"file_path == '" + filePath + "' AND "
|
||||
"line_number == " + std::to_string(lineNumber) + " AND "
|
||||
"column_number == " + std::to_string(columnNumber) + ";"
|
||||
).c_str());
|
||||
|
||||
if (!q.eof())
|
||||
{
|
||||
return q.getIntField(0, -1);
|
||||
}
|
||||
|
||||
std::cout << ("INSERT INTO error(message, file_path, line_number, column_number) "
|
||||
"VALUES ('" + sanitizedMessage + "', '" + filePath + "', " + std::to_string(lineNumber) + ", " + std::to_string(columnNumber) + ");") << std::endl;
|
||||
|
||||
m_database.execDML((
|
||||
"INSERT INTO error(message, file_path, line_number, column_number) "
|
||||
"VALUES ('" + sanitizedMessage + "', '" + filePath + "', " + std::to_string(lineNumber) + ", " + std::to_string(columnNumber) + ");"
|
||||
).c_str());
|
||||
|
||||
return m_database.lastRowId();
|
||||
}
|
||||
|
||||
void SqliteStorage::removeElement(Id id)
|
||||
{
|
||||
m_database.execDML((
|
||||
@@ -231,6 +260,13 @@ void SqliteStorage::removeUnusedNameHierarchyElements()
|
||||
);
|
||||
}
|
||||
|
||||
void SqliteStorage::removeErrorsInFiles(const std::vector<FilePath>& filePaths)
|
||||
{
|
||||
m_database.execDML((
|
||||
"DELETE FROM error WHERE file_path IN ('" + utility::join(utility::toStrings(filePaths), "', '") + "');"
|
||||
).c_str());
|
||||
}
|
||||
|
||||
StorageNode SqliteStorage::getFirstNode() const
|
||||
{
|
||||
std::vector<StorageNode> nodes = getAllNodes("LIMIT 1");
|
||||
@@ -691,6 +727,28 @@ Id SqliteStorage::getNodeIdBySignature(const std::string& signature) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<StorageError> SqliteStorage::getAllErrors() const
|
||||
{
|
||||
CppSQLite3Query q = m_database.execQuery(
|
||||
"SELECT message, file_path, line_number, column_number FROM error;"
|
||||
);
|
||||
|
||||
std::vector<StorageError> errors;
|
||||
while (!q.eof())
|
||||
{
|
||||
const std::string message = q.getStringField(0, "");
|
||||
const std::string filePath = q.getStringField(1, "");
|
||||
const uint lineNumber = q.getIntField(2, 0);
|
||||
const uint columnNumber = q.getIntField(3, 0);
|
||||
|
||||
errors.push_back(StorageError(message, filePath, lineNumber, columnNumber));
|
||||
|
||||
q.nextRow();
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int SqliteStorage::getNodeCount() const
|
||||
{
|
||||
return m_database.execScalar("SELECT COUNT(*) FROM node;");
|
||||
@@ -718,6 +776,7 @@ int SqliteStorage::getSourceLocationCount() const
|
||||
|
||||
void SqliteStorage::clearTables()
|
||||
{
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.error;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.function_signature;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.component_access;");
|
||||
m_database.execDML("DROP TABLE IF EXISTS main.source_location;");
|
||||
@@ -818,6 +877,16 @@ void SqliteStorage::setupTables()
|
||||
"PRIMARY KEY(id), "
|
||||
"FOREIGN KEY(id) REFERENCES node(id) ON DELETE CASCADE);"
|
||||
);
|
||||
|
||||
m_database.execDML(
|
||||
"CREATE TABLE IF NOT EXISTS error("
|
||||
"id INTEGER NOT NULL, "
|
||||
"message TEXT, "
|
||||
"file_path TEXT, "
|
||||
"line_number INTEGER, "
|
||||
"column_number INTEGER, "
|
||||
"PRIMARY KEY(id));"
|
||||
);
|
||||
}
|
||||
|
||||
bool SqliteStorage::hasTable(const std::string& tableName) const
|
||||
|
||||
@@ -42,6 +42,8 @@ public:
|
||||
Id addComponentAccess(Id memberEdgeId, int type);
|
||||
Id addSignature(Id nodeId, const std::string& signature);
|
||||
|
||||
Id addError(const std::string& message, const std::string& filePath, uint lineNumber, uint columnNumber);
|
||||
|
||||
void removeElement(Id id);
|
||||
void removeNameHierarchyElement(Id id);
|
||||
void removeElementsWithLocationInFiles(const std::vector<Id>& fileIds);
|
||||
@@ -49,6 +51,8 @@ public:
|
||||
void removeFiles(const std::vector<Id>& fileIds);
|
||||
void removeUnusedNameHierarchyElements();
|
||||
|
||||
void removeErrorsInFiles(const std::vector<FilePath>& filePaths);
|
||||
|
||||
StorageNode getFirstNode() const;
|
||||
std::vector<StorageNode> getAllNodes() const;
|
||||
|
||||
@@ -101,6 +105,8 @@ public:
|
||||
std::vector<StorageComponentAccess> getComponentAccessByMemberEdgeIds(const std::vector<Id>& memberEdgeIds) const;
|
||||
Id getNodeIdBySignature(const std::string& signature) const;
|
||||
|
||||
std::vector<StorageError> getAllErrors() const;
|
||||
|
||||
int getNodeCount() const;
|
||||
int getEdgeCount() const;
|
||||
int getFileCount() const;
|
||||
|
||||
+16
-36
@@ -41,9 +41,6 @@ void Storage::clear()
|
||||
m_sqliteStorage.clear();
|
||||
|
||||
clearCaches();
|
||||
|
||||
m_errorMessages.clear();
|
||||
m_errorLocationCollection.clear();
|
||||
}
|
||||
|
||||
void Storage::clearCaches()
|
||||
@@ -96,6 +93,8 @@ void Storage::clearFileElements(const std::vector<FilePath>& filePaths)
|
||||
{
|
||||
m_sqliteStorage.removeElementsWithLocationInFiles(fileNodeIds);
|
||||
m_sqliteStorage.removeFiles(fileNodeIds);
|
||||
|
||||
m_sqliteStorage.removeErrorsInFiles(filePaths);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,41 +182,12 @@ void Storage::onError(const ParseLocation& location, const std::string& message)
|
||||
return;
|
||||
}
|
||||
|
||||
bool duplicate = false;
|
||||
TokenLocationFile* file = m_errorLocationCollection.findTokenLocationFileByPath(location.filePath);
|
||||
|
||||
if (file)
|
||||
{
|
||||
file->forEachStartTokenLocation(
|
||||
[&](TokenLocation* loc)
|
||||
{
|
||||
if (loc->getLineNumber() == location.startLineNumber &&
|
||||
loc->getColumnNumber() == location.startColumnNumber &&
|
||||
m_errorMessages[loc->getTokenId()] == message)
|
||||
{
|
||||
duplicate = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!duplicate)
|
||||
{
|
||||
Id errorId = m_errorMessages.size();
|
||||
|
||||
m_errorLocationCollection.addTokenLocation(
|
||||
getErrorCount(), errorId, location.filePath,
|
||||
location.startLineNumber, location.startColumnNumber,
|
||||
location.endLineNumber, location.endColumnNumber
|
||||
);
|
||||
|
||||
m_errorMessages.push_back(message);
|
||||
}
|
||||
m_sqliteStorage.addError(message, location.filePath.str(), location.startLineNumber, location.startColumnNumber);
|
||||
}
|
||||
|
||||
size_t Storage::getErrorCount() const
|
||||
{
|
||||
return m_errorLocationCollection.getTokenLocationCount();
|
||||
return m_sqliteStorage.getAllErrors().size();
|
||||
}
|
||||
|
||||
Id Storage::onTypedefParsed(
|
||||
@@ -1176,8 +1146,18 @@ std::shared_ptr<TokenLocationFile> Storage::getTokenLocationsForLinesInFile(
|
||||
|
||||
TokenLocationCollection Storage::getErrorTokenLocations(std::vector<std::string>* errorMessages) const
|
||||
{
|
||||
errorMessages->insert(errorMessages->begin(), m_errorMessages.begin(), m_errorMessages.end());
|
||||
return m_errorLocationCollection;
|
||||
TokenLocationCollection errorCollection;
|
||||
|
||||
std::vector<StorageError> errors = m_sqliteStorage.getAllErrors();
|
||||
for (size_t i = 0; i < errors.size(); i++)
|
||||
{
|
||||
const StorageError& error = errors[i];
|
||||
errorCollection.addTokenLocation(
|
||||
i, i, error.filePath, error.lineNumber, error.columnNumber, error.lineNumber, error.columnNumber);
|
||||
errorMessages->push_back(error.message);
|
||||
}
|
||||
|
||||
return errorCollection;
|
||||
}
|
||||
|
||||
std::shared_ptr<TokenLocationFile> Storage::getTokenLocationOfParentScope(const TokenLocation* child) const
|
||||
|
||||
@@ -203,9 +203,6 @@ private:
|
||||
mutable std::map <FilePath, Id> m_fileNodeIds;
|
||||
HierarchyCache m_hierarchyCache;
|
||||
|
||||
TokenLocationCollection m_errorLocationCollection;
|
||||
std::vector<std::string> m_errorMessages;
|
||||
|
||||
mutable SearchResults m_cachedResults;
|
||||
mutable std::string m_cachedQuery;
|
||||
};
|
||||
|
||||
@@ -80,4 +80,19 @@ struct StorageComponentAccess
|
||||
int type;
|
||||
};
|
||||
|
||||
struct StorageError
|
||||
{
|
||||
StorageError(const std::string& message, const std::string& filePath, uint lineNumber, uint columnNumber)
|
||||
: message(message)
|
||||
, filePath(filePath)
|
||||
, lineNumber(lineNumber)
|
||||
, columnNumber(columnNumber)
|
||||
{}
|
||||
|
||||
std::string message;
|
||||
std::string filePath;
|
||||
uint lineNumber;
|
||||
uint columnNumber;
|
||||
};
|
||||
|
||||
#endif // STORAGE_TYPES_H
|
||||
|
||||
Reference in New Issue
Block a user