logic: implemented Python post processing to add ambiguous edges for unsolved symbols

This commit is contained in:
mlangkabel
2019-05-07 14:17:59 +02:00
parent 7f4e03b241
commit bdb4c78399
32 changed files with 494 additions and 30 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
#!/bin/bash
SOURCETRAIL_PYTHON_INDEXER_VERSION="v0_db23_p4"
SOURCETRAIL_PYTHON_INDEXER_VERSION="v0_db24_p0"
# Determine current platform
PLATFORM='unknown'
@@ -14,7 +14,7 @@ fi
PACKAGE_NAME="SourcetrailPythonIndexer_${SOURCETRAIL_PYTHON_INDEXER_VERSION}-${PLATFORM}"
PACKAGE_FILE_NAME="${PACKAGE_NAME}.zip"
PACKAGE_URL="https://github.com/CoatiSoftware/SourcetrailPythonIndexer/releases/download/${SOURCETRAIL_PYTHON_INDEXER_VERSION}/${PACKAGE_FILE_NAME}"
PACKAGE_URL="https://github.com/CoatiSoftware/SourcetrailPythonIndexer/releases/download/${SOURCETRAIL_PYTHON_INDEXER_VERSION}_beta/${PACKAGE_FILE_NAME}"
TEMP_PATH="build/temp"
TARGET_PATH="bin/app/data/python"
+4
View File
@@ -138,11 +138,14 @@ add_files(
data/graph/token_component/TokenComponentFilePath.cpp
data/graph/token_component/TokenComponentFilePath.h
data/graph/token_component/TokenComponentInheritanceChain.h
data/graph/token_component/TokenComponentIsAmbiguous.h
data/graph/token_component/TokenComponentStatic.cpp
data/graph/token_component/TokenComponentStatic.h
data/graph/Edge.cpp
data/graph/Edge.h
data/graph/ElementComponentKind.cpp
data/graph/ElementComponentKind.h
data/graph/Graph.cpp
data/graph/Graph.h
data/graph/Node.cpp
@@ -250,6 +253,7 @@ add_files(
data/storage/type/StorageBookmarkedNode.h
data/storage/type/StorageComponentAccess.h
data/storage/type/StorageEdge.h
data/storage/type/StorageElementComponent.h
data/storage/type/StorageError.h
data/storage/type/StorageFile.h
data/storage/type/StorageLocalSymbol.h
@@ -12,6 +12,7 @@
#include "MessageRefreshUI.h"
#include "MessageStatus.h"
#include "MessageScrollToLine.h"
#include "MessageTooltipShow.h"
#include "utility.h"
ActivationController::ActivationController(StorageAccess* storageAccess)
@@ -109,6 +110,16 @@ void ActivationController::handleMessage(MessageActivateSourceLocations* message
{
msg.addNode(nodeId);
}
if (message->containsUnsolvedLocations && msg.nodes.size() == 1 &&
m_storageAccess->getNameHierarchyForNodeId(msg.nodes[0].nodeId).getQualifiedName() == L"unsolved symbol")
{
MessageTooltipShow m(message->locationIds, {}, TOOLTIP_ORIGIN_CODE);
m.force = true;
m.dispatch();
return;
}
msg.setSchedulerId(message->getSchedulerId());
msg.dispatchImmediately();
}
@@ -100,7 +100,8 @@ void IDECommunicationController::handleSetActiveTokenMessage(
{
const SourceLocation* endLocation = startLocation->getEndLocation();
if ((startLocation->getType() == LOCATION_TOKEN || startLocation->getType() == LOCATION_QUALIFIER)
if ((startLocation->getType() == LOCATION_TOKEN || startLocation->getType() == LOCATION_QUALIFIER
|| startLocation->getType() == LOCATION_UNSOLVED)
&& startLocation->getLineNumber() == endLocation->getLineNumber()
&& startLocation->getColumnNumber() <= cursorColumn
&& endLocation->getColumnNumber() + 1 >= cursorColumn)
@@ -91,9 +91,9 @@ void TooltipController::handleMessage(MessageTooltipShow* message)
// If a tooltip list would only display one token, then just activate it instead.
// This can happen when edges pointing to the token use the same source location e.g. override edges
if (info.snippets.size() == 1)
if (!message->force && info.snippets.size() == 1)
{
MessageActivateSourceLocations(message->sourceLocationIds).dispatch();
MessageActivateSourceLocations(message->sourceLocationIds, false).dispatch();
}
else if (info.snippets.size())
{
+6 -1
View File
@@ -609,7 +609,7 @@ GraphViewStyle::NodeStyle GraphViewStyle::getStyleOfGroupNode(GroupType type, bo
}
GraphViewStyle::EdgeStyle GraphViewStyle::getStyleForEdgeType(
Edge::EdgeType type, bool isActive, bool isFocused, bool isTrailEdge)
Edge::EdgeType type, bool isActive, bool isFocused, bool isTrailEdge, bool isAmbiguous)
{
EdgeStyle style;
@@ -706,6 +706,11 @@ GraphViewStyle::EdgeStyle GraphViewStyle::getStyleForEdgeType(
break;
}
if (isAmbiguous)
{
style.dashed = true;
}
return style;
}
+2 -1
View File
@@ -130,7 +130,8 @@ public:
static NodeStyle getStyleOfTextNode(int fontSizeDiff);
static NodeStyle getStyleOfGroupNode(GroupType type, bool isFocused);
static EdgeStyle getStyleForEdgeType(Edge::EdgeType type, bool isActive, bool isFocused, bool isTrailEdge);
static EdgeStyle getStyleForEdgeType(
Edge::EdgeType type, bool isActive, bool isFocused, bool isTrailEdge, bool isAmbiguous);
static int toGridOffset(int x);
static int toGridSize(int x);
@@ -0,0 +1,23 @@
#include "ElementComponentKind.h"
int elementComponentKindToInt(ElementComponentKind kind)
{
return static_cast<int>(kind);
}
ElementComponentKind intToElementComponentKind(int value)
{
const ElementComponentKind kinds[] = {
ElementComponentKind::IS_AMBIGUOUS
};
for (ElementComponentKind kind : kinds)
{
if (value == elementComponentKindToInt(kind))
{
return kind;
}
}
return ElementComponentKind::NONE;
}
+13
View File
@@ -0,0 +1,13 @@
#ifndef ELEMENT_COMPONENT_KIND_H
#define ELEMENT_COMPONENT_KIND_H
enum class ElementComponentKind
{
NONE = 0,
IS_AMBIGUOUS = 1
};
int elementComponentKindToInt(ElementComponentKind type);
ElementComponentKind intToElementComponentKind(int value);
#endif // ELEMENT_COMPONENT_KIND_H
@@ -0,0 +1,16 @@
#ifndef TOKEN_COMPONENT_IS_AMBIGUOUS_H
#define TOKEN_COMPONENT_IS_AMBIGUOUS_H
#include "TokenComponent.h"
class TokenComponentIsAmbiguous
: public TokenComponent
{
public:
inline virtual std::shared_ptr<TokenComponent> copy() const
{
return std::make_shared<TokenComponentIsAmbiguous>(*this);
}
};
#endif // TOKEN_COMPONENT_IS_AMBIGUOUS_H
+21 -1
View File
@@ -19,6 +19,26 @@ IndexerCommandCustom::IndexerCommandCustom(
bool runInParallel
)
: IndexerCommand(sourceFilePath)
, m_type(getStaticIndexerCommandType())
, m_customCommand(customCommand)
, m_projectFilePath(projectFilePath)
, m_databaseFilePath(databaseFilePath)
, m_databaseVersion(databaseVersion)
, m_runInParallel(runInParallel)
{
}
IndexerCommandCustom::IndexerCommandCustom(
IndexerCommandType type,
const std::wstring& customCommand,
const FilePath& projectFilePath,
const FilePath& databaseFilePath,
const std::wstring& databaseVersion,
const FilePath& sourceFilePath,
bool runInParallel
)
: IndexerCommand(sourceFilePath)
, m_type(type)
, m_customCommand(customCommand)
, m_projectFilePath(projectFilePath)
, m_databaseFilePath(databaseFilePath)
@@ -29,7 +49,7 @@ IndexerCommandCustom::IndexerCommandCustom(
IndexerCommandType IndexerCommandCustom::getIndexerCommandType() const
{
return getStaticIndexerCommandType();
return m_type;
}
size_t IndexerCommandCustom::getByteSize(size_t stringSize) const
+11 -1
View File
@@ -13,7 +13,16 @@ public:
static IndexerCommandType getStaticIndexerCommandType();
IndexerCommandCustom(
const std::wstring& customCommand,
const std::wstring& customCommand,
const FilePath& projectFilePath,
const FilePath& databaseFilePath,
const std::wstring& databaseVersion,
const FilePath& sourceFilePath,
bool runInParallel);
IndexerCommandCustom(
IndexerCommandType type,
const std::wstring& customCommand,
const FilePath& projectFilePath,
const FilePath& databaseFilePath,
const std::wstring& databaseVersion,
@@ -33,6 +42,7 @@ protected:
QJsonObject doSerialize() const override;
private:
IndexerCommandType m_type;
std::wstring m_customCommand;
FilePath m_projectFilePath;
FilePath m_databaseFilePath;
@@ -22,7 +22,6 @@ IndexerCommandType stringToIndexerCommandType(const std::string& s)
{
if (s == indexerCommandTypeToString(INDEXER_COMMAND_CXX)) return INDEXER_COMMAND_CXX;
if (s == indexerCommandTypeToString(INDEXER_COMMAND_JAVA)) return INDEXER_COMMAND_JAVA;
if (s == indexerCommandTypeToString(INDEXER_COMMAND_PYTHON)) return INDEXER_COMMAND_PYTHON;
if (s == indexerCommandTypeToString(INDEXER_COMMAND_CUSTOM)) return INDEXER_COMMAND_CUSTOM;
return INDEXER_COMMAND_UNKNOWN;
}
@@ -1,7 +1,9 @@
#include "TaskExecuteCustomCommands.h"
#include "ApplicationSettings.h"
#include "Blackboard.h"
#include "DialogView.h"
#include "ElementComponentKind.h"
#include "FileSystem.h"
#include "IndexerCommandCustom.h"
#include "IndexerCommandProvider.h"
@@ -9,6 +11,9 @@
#include "MessageShowStatus.h"
#include "MessageStatus.h"
#include "PersistentStorage.h"
#include "SourceLocationCollection.h"
#include "SourceLocationFile.h"
#include "TextAccess.h"
#include "utility.h"
#include "utilityApp.h"
#include "utilityString.h"
@@ -26,6 +31,7 @@ TaskExecuteCustomCommands::TaskExecuteCustomCommands(
, m_indexerThreadCount(indexerThreadCount)
, m_projectDirectory(projectDirectory)
, m_indexerCommandCount(m_indexerCommandProvider->size())
, m_hasPythonCommands(false)
{
}
@@ -46,6 +52,11 @@ void TaskExecuteCustomCommands::doEnter(std::shared_ptr<Blackboard> blackboard)
m_targetDatabaseFilePath = indexerCommand->getDatabaseFilePath();
}
if (indexerCommand->getIndexerCommandType() == INDEXER_COMMAND_PYTHON)
{
m_hasPythonCommands = true;
}
if (indexerCommand->getRunInParallel())
{
m_parallelCommands.push_back(indexerCommand);
@@ -66,7 +77,7 @@ Task::TaskState TaskExecuteCustomCommands::doUpdate(std::shared_ptr<Blackboard>
return STATE_SUCCESS;
}
m_dialogView->updateCustomIndexingDialog(0, 0, m_indexerCommandProvider->size(), { });
m_dialogView->updateCustomIndexingDialog(0, 0, m_indexerCommandProvider->size(), {});
std::vector<std::shared_ptr<std::thread>> indexerThreads;
@@ -105,6 +116,11 @@ Task::TaskState TaskExecuteCustomCommands::doUpdate(std::shared_ptr<Blackboard>
}
FileSystem::remove(sourceDatabaseFilePath);
}
if (m_hasPythonCommands && ApplicationSettings::getInstance()->getPythonPostProcessingEnabled())
{
runPythonPostProcessing(targetStorage);
}
}
return STATE_SUCCESS;
@@ -143,7 +159,6 @@ void TaskExecuteCustomCommands::executeParallelIndexerCommands(int threadId, std
}
indexerCommand = m_parallelCommands.back();
m_parallelCommands.pop_back();
}
if (threadId != 0)
@@ -235,4 +250,115 @@ void TaskExecuteCustomCommands::runIndexerCommand(std::shared_ptr<IndexerCommand
indexedSourceFileCount++;
blackboard->update<int>("indexed_source_file_count", [=](int count) { return count + 1; });
}
}
}
void TaskExecuteCustomCommands::runPythonPostProcessing(PersistentStorage& storage)
{
LOG_INFO("Starting Python post processing.");
std::vector<Id> unsolvedLocationIds;
for (const StorageSourceLocation location : storage.getStorageSourceLocations())
{
if (intToLocationType(location.type) == LOCATION_UNSOLVED)
{
unsolvedLocationIds.push_back(location.id);
}
}
std::shared_ptr<SourceLocationCollection> locationCollection = storage.getSourceLocationsForLocationIds(unsolvedLocationIds);
std::map<std::wstring, std::vector<StorageNode>> nodeNameToStorageNodes;
if (locationCollection->getSourceLocationCount() > 0)
{
for (const StorageNode& node : storage.getStorageNodes())
{
nodeNameToStorageNodes[NameHierarchy::deserialize(node.serializedName).back().getName()].push_back(node);
}
}
struct DataToInsert
{
StorageEdgeData edgeData;
Id sourceLocationId;
};
storage.setMode(SqliteIndexStorage::STORAGE_MODE_READ);
std::vector<DataToInsert> dataToInsert;
std::set<Id> elementsToDelete;
locationCollection->forEachSourceLocationFile([&nodeNameToStorageNodes, &storage, &dataToInsert, &elementsToDelete](std::shared_ptr<SourceLocationFile> locationFile)
{
std::shared_ptr<TextAccess> textAccess = TextAccess::createFromFile(locationFile->getFilePath());
if (textAccess)
{
locationFile->forEachStartSourceLocation([textAccess, &nodeNameToStorageNodes, &storage, &dataToInsert, &elementsToDelete](const SourceLocation* startLoc)
{
if (!startLoc)
{
return;
}
const SourceLocation* endLoc = startLoc->getOtherLocation();
if (!endLoc)
{
return;
}
const std::wstring token = utility::decodeFromUtf8(textAccess->getLine(startLoc->getLineNumber()).substr(startLoc->getColumnNumber() - 1, endLoc->getColumnNumber() - startLoc->getColumnNumber() + 1));
for (const Id tokenId : startLoc->getTokenIds())
{
const StorageEdge edge = storage.getEdgeById(tokenId);
if (edge.id != 0)
{
for (const StorageNode& targetNode : nodeNameToStorageNodes[token])
{
if (Edge::intToType(edge.type) == Edge::EDGE_CALL &&
(
NodeType::intToType(targetNode.type) != NodeType::NODE_FUNCTION ||
NodeType::intToType(targetNode.type) != NodeType::NODE_METHOD
)
){
continue;
}
dataToInsert.push_back({ StorageEdgeData(edge.type, edge.sourceNodeId, targetNode.id) , startLoc->getLocationId() });
elementsToDelete.insert(edge.id);
}
}
}
}
);
}
}
);
storage.setMode(SqliteIndexStorage::STORAGE_MODE_WRITE);
storage.startInjection();
std::vector<StorageEdge> edgesToInsert;
for (const DataToInsert& data : dataToInsert)
{
edgesToInsert.push_back(StorageEdge(0, data.edgeData));
}
const std::vector<Id> ambiguousEdgeIds = storage.addEdges(edgesToInsert);
if (ambiguousEdgeIds.size() == dataToInsert.size())
{
for (size_t i = 0; i < ambiguousEdgeIds.size(); i++)
{
storage.addElementComponent(StorageElementComponentData(ambiguousEdgeIds[i], elementComponentKindToInt(ElementComponentKind::IS_AMBIGUOUS), L""));
storage.addOccurrence(StorageOccurrence(ambiguousEdgeIds[i], dataToInsert[i].sourceLocationId));
}
storage.removeElements(utility::toVector(elementsToDelete));
storage.finishInjection();
}
else
{
LOG_ERROR("Error occurred while running Python post processing. Rolling back all changes.");
storage.rollbackInjection();
}
LOG_INFO("Finished Python post processing.");
}
@@ -37,7 +37,9 @@ private:
void executeParallelIndexerCommands(int threadId, std::shared_ptr<Blackboard> blackboard);
void runIndexerCommand(std::shared_ptr<IndexerCommandCustom> indexerCommand, std::shared_ptr<Blackboard> blackboard);
public:
static void runPythonPostProcessing(PersistentStorage& storage);
private:
std::unique_ptr<IndexerCommandProvider> m_indexerCommandProvider;
std::shared_ptr<PersistentStorage> m_storage;
std::shared_ptr<DialogView> m_dialogView;
@@ -51,6 +53,7 @@ private:
std::vector<std::shared_ptr<IndexerCommandCustom>> m_parallelCommands;
std::mutex m_parallelCommandsMutex;
FilePath m_targetDatabaseFilePath;
bool m_hasPythonCommands;
std::set<FilePath> m_sourceDatabaseFilePaths;
std::mutex m_sourceDatabaseFilePathsMutex;
};
+2
View File
@@ -27,6 +27,8 @@ LocationType intToLocationType(int value)
return LOCATION_FULLTEXT_SEARCH;
case LOCATION_SCREEN_SEARCH:
return LOCATION_SCREEN_SEARCH;
case LOCATION_UNSOLVED:
return LOCATION_UNSOLVED;
}
return LOCATION_TOKEN;
}
+2 -1
View File
@@ -11,7 +11,8 @@ enum LocationType
LOCATION_COMMENT = 5,
LOCATION_ERROR = 6,
LOCATION_FULLTEXT_SEARCH = 7,
LOCATION_SCREEN_SEARCH = 8
LOCATION_SCREEN_SEARCH = 8,
LOCATION_UNSOLVED = 9
};
int locationTypeToInt(LocationType type);
+52 -4
View File
@@ -7,10 +7,12 @@
#include "TokenComponentAggregation.h"
#include "TokenComponentFilePath.h"
#include "TokenComponentInheritanceChain.h"
#include "TokenComponentIsAmbiguous.h"
#include "Graph.h"
#include "SourceLocationCollection.h"
#include "SourceLocationFile.h"
#include "AccessKind.h"
#include "ElementComponentKind.h"
#include "ParseLocation.h"
#include "NodeTypeSet.h"
#include "ApplicationSettings.h"
@@ -138,11 +140,26 @@ void PersistentStorage::addComponentAccesses(const std::vector<StorageComponentA
m_sqliteIndexStorage.addComponentAccesses(componentAccesses);
}
void PersistentStorage::addElementComponent(const StorageElementComponentData& data)
{
m_sqliteIndexStorage.addElementComponent(data);
}
Id PersistentStorage::addError(const StorageErrorData& data)
{
return m_sqliteIndexStorage.addError(data).id;
}
void PersistentStorage::removeElement(const Id id)
{
m_sqliteIndexStorage.removeElement(id);
}
void PersistentStorage::removeElements(const std::vector<Id>& ids)
{
m_sqliteIndexStorage.removeElements(ids);
}
const std::vector<StorageNode>& PersistentStorage::getStorageNodes() const
{
return m_storageData.nodes = m_sqliteIndexStorage.getAll<StorageNode>();
@@ -207,6 +224,13 @@ void PersistentStorage::finishInjection()
afterErrorRecording();
}
void PersistentStorage::rollbackInjection()
{
m_sqliteIndexStorage.rollbackTransaction();
afterErrorRecording();
}
void PersistentStorage::beforeErrorRecording()
{
m_preInjectionErrorCount = m_sqliteIndexStorage.getErrorCount();
@@ -1170,6 +1194,7 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForActiveTokenIds(
}
addComponentAccessToGraph(graph);
addComponentIsAmbiguousToGraph(graph);
if (isActiveNamespace)
{
@@ -1258,6 +1283,7 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForTrail(
addNodesWithParentsAndEdgesToGraph(utility::toVector(nodeIds), utility::toVector(edgeIds), graph.get(), false);
addComponentAccessToGraph(graph.get());
addComponentIsAmbiguousToGraph(graph.get());
return graph;
}
@@ -1382,7 +1408,7 @@ std::shared_ptr<SourceLocationCollection> PersistentStorage::getSourceLocationsF
for (const StorageSourceLocation& sourceLocation: m_sqliteIndexStorage.getAllByIds<StorageSourceLocation>(locationIds))
{
const LocationType type = intToLocationType(sourceLocation.type);
if (type != LOCATION_TOKEN && type != LOCATION_SCOPE && type != LOCATION_LOCAL_SYMBOL)
if (type != LOCATION_TOKEN && type != LOCATION_SCOPE && type != LOCATION_LOCAL_SYMBOL && type != LOCATION_UNSOLVED)
{
continue;
}
@@ -1446,7 +1472,7 @@ std::shared_ptr<SourceLocationCollection> PersistentStorage::getSourceLocationsF
}
const LocationType type = intToLocationType(location.type);
if (type != LOCATION_TOKEN && type != LOCATION_SCOPE && type != LOCATION_LOCAL_SYMBOL)
if (type != LOCATION_TOKEN && type != LOCATION_SCOPE && type != LOCATION_LOCAL_SYMBOL && type != LOCATION_UNSOLVED)
{
continue;
}
@@ -1473,7 +1499,7 @@ std::shared_ptr<SourceLocationFile> PersistentStorage::getSourceLocationsForFile
TRACE();
return m_sqliteIndexStorage.getSourceLocationsForFile(filePath)->getFilteredByTypes({
LOCATION_TOKEN, LOCATION_SCOPE, LOCATION_QUALIFIER, LOCATION_LOCAL_SYMBOL
LOCATION_TOKEN, LOCATION_SCOPE, LOCATION_QUALIFIER, LOCATION_LOCAL_SYMBOL, LOCATION_UNSOLVED
});
}
@@ -1485,7 +1511,7 @@ std::shared_ptr<SourceLocationFile> PersistentStorage::getSourceLocationsForLine
return m_sqliteIndexStorage.getSourceLocationsForLinesInFile(
filePath, startLine, endLine)->getFilteredByLines(startLine, endLine)->getFilteredByTypes({
LOCATION_TOKEN, LOCATION_SCOPE, LOCATION_QUALIFIER, LOCATION_LOCAL_SYMBOL
LOCATION_TOKEN, LOCATION_SCOPE, LOCATION_QUALIFIER, LOCATION_LOCAL_SYMBOL, LOCATION_UNSOLVED
});
}
@@ -2819,6 +2845,28 @@ void PersistentStorage::addComponentAccessToGraph(Graph* graph) const
}
}
void PersistentStorage::addComponentIsAmbiguousToGraph(Graph* graph) const
{
TRACE();
std::vector<Id> edgeIds;
graph->forEachEdge(
[&edgeIds](Edge* edge)
{
edgeIds.push_back(edge->getId());
}
);
int componentKind = elementComponentKindToInt(ElementComponentKind::IS_AMBIGUOUS);
for (const StorageElementComponent& component : m_sqliteIndexStorage.getElementComponentsByElementIds(edgeIds))
{
if (component.type == componentKind)
{
graph->getEdgeById(component.elementId)->addComponent(std::make_shared<TokenComponentIsAmbiguous>());
}
}
}
void PersistentStorage::addCompleteFlagsToSourceLocationCollection(SourceLocationCollection* collection) const
{
TRACE();
+6
View File
@@ -34,8 +34,12 @@ public:
void addOccurrences(const std::vector<StorageOccurrence>& occurrences) override;
void addComponentAccess(const StorageComponentAccess& componentAccess) override;
void addComponentAccesses(const std::vector<StorageComponentAccess>& componentAccesses) override;
void addElementComponent(const StorageElementComponentData& data) /*override*/;
Id addError(const StorageErrorData& data) override;
void removeElement(const Id id);
void removeElements(const std::vector<Id>& ids);
const std::vector<StorageNode>& getStorageNodes() const override;
const std::vector<StorageFile>& getStorageFiles() const override;
const std::vector<StorageSymbol>& getStorageSymbols() const override;
@@ -48,6 +52,7 @@ public:
void startInjection() override;
void finishInjection() override;
void rollbackInjection();
void beforeErrorRecording();
void afterErrorRecording();
@@ -198,6 +203,7 @@ private:
void addAggregationEdgesToGraph(Id nodeId, const std::vector<StorageEdge>& edgesToAggregate, Graph* graph) const;
void addFileContentsToGraph(Id fileId, Graph* graph) const;
void addComponentAccessToGraph(Graph* graph) const;
void addComponentIsAmbiguousToGraph(Graph* graph) const;
void addCompleteFlagsToSourceLocationCollection(SourceLocationCollection* collection) const;
void addInheritanceChainsToGraph(const std::vector<Id>& nodeIds, Graph* graph) const;
@@ -11,7 +11,7 @@
#include "SourceLocationFile.h"
#include "utilityString.h"
const size_t SqliteIndexStorage::s_storageVersion = 23;
const size_t SqliteIndexStorage::s_storageVersion = 24;
namespace
{
@@ -424,6 +424,17 @@ bool SqliteIndexStorage::addComponentAccesses(const std::vector<StorageComponent
return m_insertComponentAccessBatchStatement.execute(componentAccesses, this);
}
int SqliteIndexStorage::addElementComponent(const StorageElementComponentData& storageElementComponentData)
{
m_insertElementComponentStmt.bind(1, int(storageElementComponentData.elementId));
m_insertElementComponentStmt.bind(2, storageElementComponentData.type);
m_insertElementComponentStmt.bind(3, utility::encodeToUtf8(storageElementComponentData.data).c_str());
executeStatement(m_insertElementComponentStmt);
int id = m_database.lastRowId();
m_insertElementComponentStmt.reset();
return id;
}
StorageError SqliteIndexStorage::addError(const StorageErrorData& data)
{
const std::wstring sanitizedMessage = utility::replace(data.message, L"'", L"''");
@@ -968,6 +979,11 @@ std::vector<StorageComponentAccess> SqliteIndexStorage::getComponentAccessesByNo
return doGetAll<StorageComponentAccess>("WHERE node_id IN (" + utility::join(utility::toStrings(nodeIds), ',') + ")");
}
std::vector<StorageElementComponent> SqliteIndexStorage::getElementComponentsByElementIds(const std::vector<Id>& elementIds) const
{
return doGetAll<StorageElementComponent>("WHERE element_id IN (" + utility::join(utility::toStrings(elementIds), ',') + ")");
}
std::vector<ErrorInfo> SqliteIndexStorage::getAllErrorInfos() const
{
std::vector<ErrorInfo> errorInfos;
@@ -1107,6 +1123,7 @@ void SqliteIndexStorage::clearTables()
m_database.execDML("DROP TABLE IF EXISTS main.symbol;");
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_component;");
m_database.execDML("DROP TABLE IF EXISTS main.element;");
m_database.execDML("DROP TABLE IF EXISTS main.meta;");
}
@@ -1126,6 +1143,17 @@ void SqliteIndexStorage::setupTables()
"PRIMARY KEY(id));"
);
m_database.execDML(
"CREATE TABLE IF NOT EXISTS element_component("
" id INTEGER, "
" element_id INTEGER, "
" type INTEGER, "
" data TEXT, "
" PRIMARY KEY(id), "
" FOREIGN KEY(element_id) REFERENCES element(id) ON DELETE CASCADE"
");"
);
m_database.execDML(
"CREATE TABLE IF NOT EXISTS edge("
"id INTEGER NOT NULL, "
@@ -1319,6 +1347,9 @@ void SqliteIndexStorage::setupPrecompiledStatements()
m_insertElementStmt = m_database.compileStatement(
"INSERT INTO element(id) VALUES(NULL);"
);
m_insertElementComponentStmt = m_database.compileStatement(
"INSERT INTO element_component(id, element_id, type, data) VALUES(NULL, ?, ?, ?);"
);
m_insertFileStmt = m_database.compileStatement(
"INSERT INTO file(id, path, language, modification_time, indexed, complete, line_count) VALUES(?, ?, ?, ?, ?, ?, ?);"
);
@@ -1526,6 +1557,31 @@ void SqliteIndexStorage::forEach<StorageComponentAccess>(const std::string& quer
}
}
template <>
void SqliteIndexStorage::forEach<StorageElementComponent>(const std::string& query, std::function<void(StorageElementComponent&&)> func) const
{
CppSQLite3Query q = executeQuery(
"SELECT id, element_id, type, data FROM element_component " + query + ";"
);
while (!q.eof())
{
const Id id = q.getIntField(0, 0);
const Id elementId = q.getIntField(1, 0);
const int type = q.getIntField(2, -1);
const std::string data = q.getStringField(3, "");
if (id != 0 && elementId != 0 && type != -1)
{
func(StorageElementComponent(
id, elementId, type, utility::decodeFromUtf8(data)
));
}
q.nextRow();
}
}
template <>
void SqliteIndexStorage::forEach<StorageError>(const std::string& query, std::function<void(StorageError&&)> func) const
{
@@ -13,6 +13,7 @@
#include "StorageComponentAccess.h"
#include "StorageEdge.h"
#include "StorageError.h"
#include "StorageElementComponent.h"
#include "StorageFile.h"
#include "StorageLocalSymbol.h"
#include "StorageNode.h"
@@ -65,6 +66,7 @@ public:
bool addOccurrences(const std::vector<StorageOccurrence>& occurrences);
bool addComponentAccess(const StorageComponentAccess& componentAccess);
bool addComponentAccesses(const std::vector<StorageComponentAccess>& componentAccesses);
int addElementComponent(const StorageElementComponentData& storageElementComponentData);
StorageError addError(const StorageErrorData& data);
void removeElement(Id id);
@@ -118,8 +120,10 @@ public:
std::vector<StorageOccurrence> getOccurrencesForLocationIds(const std::vector<Id>& locationIds) const;
std::vector<StorageOccurrence> getOccurrencesForElementIds(const std::vector<Id>& elementIds) const;
StorageComponentAccess getComponentAccessByNodeId(Id memberEdgeId) const;
std::vector<StorageComponentAccess> getComponentAccessesByNodeIds(const std::vector<Id>& memberEdgeIds) const;
StorageComponentAccess getComponentAccessByNodeId(Id nodeId) const;
std::vector<StorageComponentAccess> getComponentAccessesByNodeIds(const std::vector<Id>& nodeIds) const;
std::vector<StorageElementComponent> getElementComponentsByElementIds(const std::vector<Id>& elementIds) const;
std::vector<ErrorInfo> getAllErrorInfos() const;
@@ -351,6 +355,7 @@ private:
InsertBatchStatement<StorageComponentAccess> m_insertComponentAccessBatchStatement;
CppSQLite3Statement m_insertElementStmt;
CppSQLite3Statement m_insertElementComponentStmt;
CppSQLite3Statement m_insertFileStmt;
CppSQLite3Statement m_insertFileContentStmt;
CppSQLite3Statement m_checkErrorExistsStmt;
@@ -374,6 +379,8 @@ void SqliteIndexStorage::forEach<StorageOccurrence>(const std::string& query, st
template <>
void SqliteIndexStorage::forEach<StorageComponentAccess>(const std::string& query, std::function<void(StorageComponentAccess&&)> func) const;
template <>
void SqliteIndexStorage::forEach<StorageElementComponent>(const std::string& query, std::function<void(StorageElementComponent&&)> func) const;
template <>
void SqliteIndexStorage::forEach<StorageError>(const std::string& query, std::function<void(StorageError&&)> func) const;
#endif // SQLITE_INDEX_STORAGE_H
@@ -0,0 +1,47 @@
#ifndef STORAGE_ELEMENT_COMPONENT_H
#define STORAGE_ELEMENT_COMPONENT_H
#include <string>
#include "types.h"
struct StorageElementComponentData
{
StorageElementComponentData()
: elementId(0)
, type(0)
, data(L"")
{}
StorageElementComponentData(Id elementId, int type, std::wstring data)
: elementId(elementId)
, type(type)
, data(std::move(data))
{}
Id elementId;
int type;
std::wstring data;
};
struct StorageElementComponent : public StorageElementComponentData
{
StorageElementComponent()
: StorageElementComponentData()
, id(0)
{}
StorageElementComponent(Id id, const StorageElementComponentData& data)
: StorageElementComponentData(data)
, id(id)
{}
StorageElementComponent(Id id, Id elementId, int type, std::wstring data)
: StorageElementComponentData(elementId, type, data)
, id(id)
{}
Id id;
};
#endif // STORAGE_ELEMENT_COMPONENT_H
+10
View File
@@ -400,6 +400,16 @@ void ApplicationSettings::setHasPrefilledMavenPath(bool v)
setValue<bool>("indexing/java/has_prefilled_maven_path", v);
}
bool ApplicationSettings::getPythonPostProcessingEnabled() const
{
return getValue<bool>("indexing/python/post_processing", true);
}
void ApplicationSettings::setPythonPostProcessingEnabled(bool enabled)
{
setValue<bool>("indexing/python/post_processing", enabled);
}
std::vector<FilePath> ApplicationSettings::getHeaderSearchPaths() const
{
return getPathValues("indexing/cxx/header_search_paths/header_search_path");
+3
View File
@@ -115,6 +115,9 @@ public:
bool getHasPrefilledMavenPath() const;
void setHasPrefilledMavenPath(bool v);
bool getPythonPostProcessingEnabled() const;
void setPythonPostProcessingEnabled(bool enabled);
std::vector<FilePath> getHeaderSearchPaths() const;
std::vector<FilePath> getHeaderSearchPathsExpanded() const;
bool setHeaderSearchPaths(const std::vector<FilePath>& headerSearchPaths);
@@ -9,8 +9,9 @@ class MessageActivateSourceLocations
: public Message<MessageActivateSourceLocations>
{
public:
MessageActivateSourceLocations(const std::vector<Id>& locationIds)
MessageActivateSourceLocations(const std::vector<Id>& locationIds, bool containsUnsolvedLocations)
: locationIds(locationIds)
, containsUnsolvedLocations(containsUnsolvedLocations)
{
setSchedulerId(TabId::currentTab());
}
@@ -29,6 +30,7 @@ public:
}
const std::vector<Id> locationIds;
const bool containsUnsolvedLocations;
};
#endif // MESSAGE_ACTIVATE_SOURCE_LOCATIONS_H
@@ -38,6 +38,8 @@ public:
const std::vector<Id> localSymbolIds;
const TooltipOrigin origin;
bool force = false;
};
#endif // MESSAGE_TOOLTIP_SHOW_H
+19 -5
View File
@@ -217,7 +217,12 @@ void QtCodeField::paintEvent(QPaintEvent* event)
continue;
}
painter.setPen(QPen(color.border.c_str()));
QPen pen(color.border.c_str());
if (annotation.locationType == LOCATION_UNSOLVED)
{
pen.setStyle(Qt::DashLine);
}
painter.setPen(pen);
painter.setBrush(QBrush(color.fill.c_str()));
if (annotation.locationType == LOCATION_SCOPE)
@@ -451,9 +456,12 @@ void QtCodeField::activateAnnotations(const std::vector<const Annotation*>& anno
std::set<Id> tokenIds;
std::set<Id> localSymbolIds;
bool containsUnsolved = false;
for (const Annotation* annotation : annotations)
{
if (annotation->locationType == LOCATION_TOKEN || annotation->locationType == LOCATION_QUALIFIER)
if (annotation->locationType == LOCATION_TOKEN || annotation->locationType == LOCATION_QUALIFIER ||
annotation->locationType == LOCATION_UNSOLVED)
{
if (annotation->locationId > 0)
{
@@ -464,6 +472,11 @@ void QtCodeField::activateAnnotations(const std::vector<const Annotation*>& anno
{
tokenIds.insert(annotation->tokenIds.begin(), annotation->tokenIds.end());
}
if (annotation->locationType == LOCATION_UNSOLVED)
{
containsUnsolved = true;
}
}
else if (annotation->locationType == LOCATION_LOCAL_SYMBOL)
{
@@ -480,7 +493,7 @@ void QtCodeField::activateAnnotations(const std::vector<const Annotation*>& anno
}
else if (locationIds.size())
{
MessageActivateSourceLocations(locationIds).dispatch();
MessageActivateSourceLocations(locationIds, containsUnsolved).dispatch();
}
else if (tokenIds.size()) // fallback for links in project description
{
@@ -681,7 +694,8 @@ std::vector<const QtCodeField::Annotation*> QtCodeField::getInteractiveAnnotatio
for (const Annotation& annotation : m_annotations)
{
const LocationType& type = annotation.locationType;
if ((type == LOCATION_TOKEN || type == LOCATION_QUALIFIER || type == LOCATION_LOCAL_SYMBOL || type == LOCATION_ERROR)
if ((type == LOCATION_TOKEN || type == LOCATION_QUALIFIER || type == LOCATION_LOCAL_SYMBOL
|| type == LOCATION_UNSOLVED || type == LOCATION_ERROR)
&& pos >= annotation.start && pos <= annotation.end)
{
annotations.push_back(&annotation);
@@ -697,7 +711,7 @@ void QtCodeField::checkOpenInTabActionEnabled(QPoint position)
for (const Annotation* annotation : getInteractiveAnnotationsForPosition(position))
{
const LocationType& type = annotation->locationType;
if (type == LOCATION_TOKEN || type == LOCATION_QUALIFIER)
if (type == LOCATION_TOKEN || type == LOCATION_QUALIFIER || type == LOCATION_UNSOLVED)
{
locationIds.emplace_back(annotation->locationId);
}
@@ -7,6 +7,7 @@
#include "Edge.h"
#include "TokenComponentAggregation.h"
#include "TokenComponentInheritanceChain.h"
#include "TokenComponentIsAmbiguous.h"
#include "QtLineItemAngled.h"
#include "QtLineItemBezier.h"
#include "QtLineItemStraight.h"
@@ -95,7 +96,8 @@ void QtGraphEdge::updateLine()
const QtGraphNode* target = m_target;
Edge::EdgeType type = (getData() ? getData()->getType() : Edge::EDGE_AGGREGATION);
GraphViewStyle::EdgeStyle style = GraphViewStyle::getStyleForEdgeType(type, m_isActive | m_isFocused, false, m_isTrailEdge);
GraphViewStyle::EdgeStyle style =
GraphViewStyle::getStyleForEdgeType(type, m_isActive | m_isFocused, false, m_isTrailEdge, isAmbiguous());
Vec4i ownerRect = owner->getBoundingRect();
Vec4i targetRect = target->getBoundingRect();
@@ -363,6 +365,11 @@ void QtGraphEdge::focusIn()
TooltipInfo info;
info.title = Edge::getReadableTypeString(type);
if (isAmbiguous())
{
info.title = L"ambiguous " + info.title;
}
if (type == Edge::EDGE_AGGREGATION && m_direction == TokenComponentAggregation::DIRECTION_NONE)
{
info.title = L"bidirectional " + info.title;
@@ -506,3 +513,8 @@ void QtGraphEdge::clearPath()
{
m_path.clear();
}
bool QtGraphEdge::isAmbiguous() const
{
return m_data && m_data->getComponent<TokenComponentIsAmbiguous>();
}
@@ -60,6 +60,8 @@ public:
void setUseBezier(bool useBezier);
void clearPath();
bool isAmbiguous() const;
protected:
virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
@@ -373,7 +373,20 @@ void QtProjectWizzardContentPreferences::populate(QGridLayout* layout, int& row)
addGap(layout, row);
// C/C++
addTitle("Python", layout, row);
m_pythonPostProcessing = addCheckBox("Post Processing",
"Add ambiguous edges for unsolved references",
"<p>Enable a post processing step to solve unsolved references after the indexing is done. </p>"
"<p>These references will be marked \"ambiguous\" to indicate that some of these edges may never "
"be encountered during runtime of the indexed code because the post processing only relies on "
"symbol names and types.</p>",
layout, row);
addGap(layout, row);
addTitle("C/C++", layout, row);
}
@@ -447,6 +460,8 @@ void QtProjectWizzardContentPreferences::load()
{
m_mavenPath->setText(QString::fromStdWString(appSettings->getMavenPath().wstr()));
}
m_pythonPostProcessing->setChecked(appSettings->getPythonPostProcessingEnabled());
}
void QtProjectWizzardContentPreferences::save()
@@ -510,6 +525,8 @@ void QtProjectWizzardContentPreferences::save()
appSettings->setMavenPath(FilePath(m_mavenPath->getText().toStdWString()));
}
appSettings->setPythonPostProcessingEnabled(m_pythonPostProcessing->isChecked());
appSettings->save();
}
@@ -125,6 +125,8 @@ private:
QtPathListBox* m_jreSystemLibraryPaths;
QLineEdit* m_jvmMaximumMemory;
QtLocationPicker* m_mavenPath;
QCheckBox* m_pythonPostProcessing;
};
#endif // QT_PROJECT_WIZZARD_CONTENT_PREFERENCES_H
@@ -57,6 +57,7 @@ std::vector<std::shared_ptr<IndexerCommand>> SourceGroupPythonEmpty::getIndexerC
if (filesToIndex.find(sourceFilePath) != filesToIndex.end())
{
indexerCommands.push_back(std::make_shared<IndexerCommandCustom>(
INDEXER_COMMAND_PYTHON,
L"\"" + ResourcePaths::getPythonPath().wstr() + L"SourcetrailPythonIndexer\"" + args,
m_settings->getProjectSettings()->getProjectFilePath(),
m_settings->getProjectSettings()->getTempDBFilePath(),