From f78a7186c11828ab8573b32c53e53a5e70f26620 Mon Sep 17 00:00:00 2001 From: mlangkabel Date: Mon, 6 May 2019 17:22:20 +0200 Subject: [PATCH] add methods to record edges as ambiguous --- core/CMakeLists.txt | 3 ++ core/include/DatabaseStorage.h | 3 ++ core/include/ElementComponentKind.h | 34 ++++++++++++++ core/include/LocationKind.h | 3 +- core/include/SourcetrailDBWriter.h | 38 +++++++++++++++ core/include/StorageElementComponent.h | 64 ++++++++++++++++++++++++++ core/src/DatabaseStorage.cpp | 28 +++++++++++ core/src/ElementComponentKind.cpp | 44 ++++++++++++++++++ core/src/LocationKind.cpp | 3 +- core/src/SourcetrailDBWriter.cpp | 57 ++++++++++++++++++++++- resources_swig/include/sourcetraildb.h | 4 ++ resources_swig/src/sourcetraildb.cpp | 10 ++++ version.txt | 2 +- 13 files changed, 289 insertions(+), 4 deletions(-) create mode 100644 core/include/ElementComponentKind.h create mode 100644 core/include/StorageElementComponent.h create mode 100644 core/src/ElementComponentKind.cpp diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index bc829fb..7a95ed5 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -16,6 +16,7 @@ set(LIB_SRC_FILES src/DatabaseStorage.cpp src/DefinitionKind.cpp src/EdgeKind.cpp + src/ElementComponentKind.cpp src/LocationKind.cpp src/NameHierarchy.cpp src/NodeKind.cpp @@ -32,6 +33,7 @@ set(LIB_HDR_FILES include/DatabaseStorage.h include/DefinitionKind.h include/EdgeKind.h + include/ElementComponentKind.h include/LocationKind.h include/NameHierarchy.h include/NodeKind.h @@ -40,6 +42,7 @@ set(LIB_HDR_FILES include/SourcetrailDBWriter.h include/SourcetrailException.h include/StorageEdge.h + include/StorageElementComponent.h include/StorageError.h include/StorageFile.h include/StorageLocalSymbol.h diff --git a/core/include/DatabaseStorage.h b/core/include/DatabaseStorage.h index a3df935..5365587 100644 --- a/core/include/DatabaseStorage.h +++ b/core/include/DatabaseStorage.h @@ -24,6 +24,7 @@ #include "CppSQLite3.h" #include "StorageEdge.h" +#include "StorageElementComponent.h" #include "StorageError.h" #include "StorageFile.h" #include "StorageLocalSymbol.h" @@ -61,6 +62,7 @@ namespace sourcetrail void rollbackTransaction(); void optimizeDatabaseMemory(); + int addElementComponent(const StorageElementComponentData& storageElementComponentData); int addNode(const StorageNodeData& storageNodeData); void addSymbol(const StorageSymbol& storageSymbol); void addFile(const StorageFile& storageFile); @@ -102,6 +104,7 @@ namespace sourcetrail mutable CppSQLite3DB m_database; CppSQLite3Statement m_insertElementStatement; + CppSQLite3Statement m_insertElementComponentStatement; CppSQLite3Statement m_findNodeStatement; CppSQLite3Statement m_insertNodeStatement; CppSQLite3Statement m_setNodeTypeStmt; diff --git a/core/include/ElementComponentKind.h b/core/include/ElementComponentKind.h new file mode 100644 index 0000000..a688c30 --- /dev/null +++ b/core/include/ElementComponentKind.h @@ -0,0 +1,34 @@ +/* +* Copyright 2018 Coati Software KG +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef SOURCETRAIL_ELEMENT_COMPONENT_KIND_H +#define SOURCETRAIL_ELEMENT_COMPONENT_KIND_H + +namespace sourcetrail +{ + /** + * Enum providing all possible values for kinds of node and edge components that can be stored to the Sourcetrail database. + */ + enum class ElementComponentKind : int + { + IS_AMBIGUOUS = 1 << 0 + }; + + int elementComponentKindToInt(ElementComponentKind kind); + ElementComponentKind intToElementComponentKind(int i); +} + +#endif // SOURCETRAIL_ELEMENT_COMPONENT_KIND_H diff --git a/core/include/LocationKind.h b/core/include/LocationKind.h index fc46396..196ea3e 100644 --- a/core/include/LocationKind.h +++ b/core/include/LocationKind.h @@ -32,7 +32,8 @@ namespace sourcetrail ATOMIC_RANGE = 5, INDEXER_ERROR = 6, FULLTEXT_SEARCH = 7, - SCREEN_SEARCH = 8 + SCREEN_SEARCH = 8, + UNSOLVED = 9 }; int locationKindToInt(LocationKind kind); diff --git a/core/include/SourcetrailDBWriter.h b/core/include/SourcetrailDBWriter.h index 636b9fa..c1486f0 100644 --- a/core/include/SourcetrailDBWriter.h +++ b/core/include/SourcetrailDBWriter.h @@ -22,6 +22,7 @@ #include "DefinitionKind.h" #include "EdgeKind.h" +#include "ElementComponentKind.h" #include "LocationKind.h" #include "NameHierarchy.h" #include "ReferenceKind.h" @@ -349,6 +350,42 @@ namespace sourcetrail */ bool recordReferenceLocation(int referenceId, const SourceRange& location); + /** + * Marks a reference that is stored in the database as "ambiguous" + * + * This method allows to additional information for a reference to the database. Sourcetrail will + * display an "ambiguous" reference with a special style to emphasize that the existance of the + * reference is questionable. This method is intended to be called in situations when an indexed + * token may have meanings, all of which shall be recorded. + * + * param: referenceId - the id of the reference that shall be marked as ambiguous. + * + * return: true if successful. false on failure. getLastError() provides the error message. + */ + bool recordReferenceIsAmbiuous(int referenceId); + + /** + * Stores a location between a specific context and an "unsolved" symbol to the database + * + * This method allows to store all available information to the database in the case that a symbol + * is referenced in a certain context but the referenced symbol could not be resolved to a concrete + * name. For each reference recorded by this method, Sourcetrail's graph view will display an edge + * that originates at the recorded context symbol and points to a node called "unsolved symbol". + * Furthermore Sourcetrail's code view will use a different highlight when the provided source range + * gets hovered. + * + * param: contextSymbolId - the id of the source of the recorded reference edge + * param: referenceKind - kind of the recorded reference edge + * param: location - the SourceRange that shall be recorded as location for the respective + * reference. + * + * return: referenceId - integer id of the stored reference. 0 on failure. getLastError() + * provides the error message. + * + * see: SourceRange + */ + int recordReferenceToUnsolvedSymhol(int contextSymbolId, ReferenceKind referenceKind, const SourceRange& location); + /** * Stores a location for the usage of a symbol's name as qualifier to the database * @@ -475,6 +512,7 @@ namespace sourcetrail int addFile(const std::string& filePath); int addEdge(int sourceId, int targetId, EdgeKind edgeKind); void addSourceLocation(int elementId, const SourceRange& location, LocationKind kind); + void addElementComponent(int elementId, ElementComponentKind kind, const std::string& data); std::string m_projectFilePath; std::string m_databaseFilePath; diff --git a/core/include/StorageElementComponent.h b/core/include/StorageElementComponent.h new file mode 100644 index 0000000..983a292 --- /dev/null +++ b/core/include/StorageElementComponent.h @@ -0,0 +1,64 @@ +/* +* Copyright 2018 Coati Software KG +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef SOURCETRAIL_STORAGE_ELEMENT_COMPONENT_H +#define SOURCETRAIL_STORAGE_ELEMENT_COMPONENT_H + +#include + +namespace sourcetrail +{ + struct StorageElementComponentData + { + StorageElementComponentData() + : elementId(0) + , componentKind(0) + , data("") + {} + + StorageElementComponentData(int elementId, int componentKind, std::string data) + : elementId(elementId) + , componentKind(componentKind) + , data(std::move(data)) + {} + + int elementId; + int componentKind; + std::string data; + }; + + struct StorageElementComponent : public StorageElementComponentData + { + StorageElementComponent() + : StorageElementComponentData() + , id(0) + {} + + StorageElementComponent(int id, const StorageElementComponentData& data) + : StorageElementComponentData(data) + , id(id) + {} + + StorageElementComponent(int id, int elementId, int componentKind, std::string data) + : StorageElementComponentData(elementId, componentKind, data) + , id(id) + {} + + int id; + }; +} + +#endif // SOURCETRAIL_STORAGE_ELEMENT_COMPONENT_H diff --git a/core/src/DatabaseStorage.cpp b/core/src/DatabaseStorage.cpp index 3f20ac8..c1366c5 100644 --- a/core/src/DatabaseStorage.cpp +++ b/core/src/DatabaseStorage.cpp @@ -151,6 +151,17 @@ namespace sourcetrail executeStatement("VACUUM;"); } + int DatabaseStorage::addElementComponent(const StorageElementComponentData& storageElementComponentData) + { + m_insertElementComponentStatement.bind(1, storageElementComponentData.elementId); + m_insertElementComponentStatement.bind(2, storageElementComponentData.componentKind); + m_insertElementComponentStatement.bind(3, storageElementComponentData.data.c_str()); + executeStatement(m_insertElementComponentStatement); + int id = m_database.lastRowId(); + m_insertElementComponentStatement.reset(); + return id; + } + int DatabaseStorage::addNode(const StorageNodeData& storageNodeData) { int id = 0; @@ -393,6 +404,17 @@ namespace sourcetrail ");" ); + executeStatement( + "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" + ");" + ); + executeStatement( "CREATE TABLE IF NOT EXISTS edge(" " id INTEGER NOT NULL, " @@ -518,6 +540,7 @@ namespace sourcetrail "symbol", "node", "edge", + "element_component" "element" }; @@ -557,6 +580,10 @@ namespace sourcetrail "INSERT INTO element(id) VALUES(NULL);" ); + m_insertElementComponentStatement = compileStatement( + "INSERT INTO element_component(id, element_id, type, data) VALUES(NULL, ?, ?, ?);" + ); + m_findNodeStatement = compileStatement( "SELECT id FROM node WHERE serialized_name == ? LIMIT 1;" ); @@ -648,6 +675,7 @@ namespace sourcetrail void DatabaseStorage::clearPrecompiledStatements() { m_insertElementStatement.finalize(); + m_insertElementComponentStatement.finalize(); m_findNodeStatement.finalize(); m_insertNodeStatement.finalize(); m_setNodeTypeStmt.finalize(); diff --git a/core/src/ElementComponentKind.cpp b/core/src/ElementComponentKind.cpp new file mode 100644 index 0000000..b82dbc5 --- /dev/null +++ b/core/src/ElementComponentKind.cpp @@ -0,0 +1,44 @@ +/* +* Copyright 2018 Coati Software KG +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "ElementComponentKind.h" + +#include "SourcetrailException.h" + +namespace sourcetrail +{ + int elementComponentKindToInt(ElementComponentKind kind) + { + return static_cast(kind); + } + + ElementComponentKind intToElementComponentKind(int i) + { + const ElementComponentKind kinds[] = { + ElementComponentKind::IS_AMBIGUOUS + }; + + for (ElementComponentKind kind : kinds) + { + if (i == elementComponentKindToInt(kind)) + { + return kind; + } + } + + throw SourcetrailException("Unable to convert integer \"" + std::to_string(i) + "\" to element component kind."); + } +} diff --git a/core/src/LocationKind.cpp b/core/src/LocationKind.cpp index a30846f..957081e 100644 --- a/core/src/LocationKind.cpp +++ b/core/src/LocationKind.cpp @@ -36,7 +36,8 @@ namespace sourcetrail LocationKind::ATOMIC_RANGE, LocationKind::INDEXER_ERROR, LocationKind::FULLTEXT_SEARCH, - LocationKind::SCREEN_SEARCH + LocationKind::SCREEN_SEARCH, + LocationKind::UNSOLVED }; for (LocationKind kind : kinds) diff --git a/core/src/SourcetrailDBWriter.cpp b/core/src/SourcetrailDBWriter.cpp index 5247623..964bde9 100644 --- a/core/src/SourcetrailDBWriter.cpp +++ b/core/src/SourcetrailDBWriter.cpp @@ -428,7 +428,7 @@ namespace sourcetrail if (!m_storage) { m_lastError = "Unable to record reference, because no database is currently open."; - return false; + return 0; } try @@ -462,6 +462,52 @@ namespace sourcetrail } } + bool SourcetrailDBWriter::recordReferenceIsAmbiuous(int referenceId) + { + if (!m_storage) + { + m_lastError = "Unable to record ambiguity of reference, because no database is currently open."; + return false; + } + + try + { + addElementComponent(referenceId, ElementComponentKind::IS_AMBIGUOUS, ""); + return false; + } + catch (const SourcetrailException e) + { + m_lastError = e.getMessage(); + return false; + } + } + + int SourcetrailDBWriter::recordReferenceToUnsolvedSymhol(int contextSymbolId, ReferenceKind referenceKind, const SourceRange& location) + { + if (!m_storage) + { + m_lastError = "Unable to record symbol reference, because no database is currently open."; + return 0; + } + + try + { + NameHierarchy unsolvedSymbolName; + NameElement unsolvedSymbolNameElement; + unsolvedSymbolNameElement.name = "unsolved symbol"; + unsolvedSymbolName.nameElements.push_back(unsolvedSymbolNameElement); + int unsolvedSymbolId = addNodeHierarchy(unsolvedSymbolName); + int referenceId = addEdge(contextSymbolId, unsolvedSymbolId, referenceKindToEdgeKind(referenceKind)); + addSourceLocation(referenceId, location, LocationKind::UNSOLVED); + return referenceId; + } + catch (const SourcetrailException e) + { + m_lastError = e.getMessage(); + return 0; + } + } + bool SourcetrailDBWriter::recordQualifierLocation(int referencedSymbolId, const SourceRange& location) { if (!m_storage) @@ -785,4 +831,13 @@ namespace sourcetrail sourceLocationId )); } + + void SourcetrailDBWriter::addElementComponent(int elementId, ElementComponentKind kind, const std::string& data) + { + const int sourceLocationId = m_storage->addElementComponent(StorageElementComponentData( + elementId, + elementComponentKindToInt(kind), + data + )); + } } diff --git a/resources_swig/include/sourcetraildb.h b/resources_swig/include/sourcetraildb.h index b810428..bc68ed4 100644 --- a/resources_swig/include/sourcetraildb.h +++ b/resources_swig/include/sourcetraildb.h @@ -95,6 +95,10 @@ int recordReference(int contextSymbolId, int referencedSymbolId, ReferenceKind r bool recordReferenceLocation(int referenceId, int fileId, int startLine, int startColumn, int endLine, int endColumn); +bool recordReferenceIsAmbiuous(int referenceId); + +int recordReferenceToUnsolvedSymhol(int contextSymbolId, ReferenceKind referenceKind, int fileId, int startLine, int startColumn, int endLine, int endColumn); + bool recordQualifierLocation(int referencedSymbolId, int fileId, int startLine, int startColumn, int endLine, int endColumn); int recordFile(std::string filePath); diff --git a/resources_swig/src/sourcetraildb.cpp b/resources_swig/src/sourcetraildb.cpp index 978df96..9312923 100644 --- a/resources_swig/src/sourcetraildb.cpp +++ b/resources_swig/src/sourcetraildb.cpp @@ -225,6 +225,16 @@ bool recordReferenceLocation(int referenceId, int fileId, int startLine, int sta return dbWriter.recordReferenceLocation(referenceId, { fileId, startLine, startColumn, endLine, endColumn }); } +bool recordReferenceIsAmbiuous(int referenceId) +{ + return dbWriter.recordReferenceIsAmbiuous(referenceId); +} + +int recordReferenceToUnsolvedSymhol(int contextSymbolId, ReferenceKind referenceKind, int fileId, int startLine, int startColumn, int endLine, int endColumn) +{ + return dbWriter.recordReferenceToUnsolvedSymhol(contextSymbolId, convertReferenceKind(referenceKind), { fileId, startLine, startColumn, endLine, endColumn }); +} + bool recordQualifierLocation(int referencedSymbolId, int fileId, int startLine, int startColumn, int endLine, int endColumn) { return dbWriter.recordQualifierLocation(referencedSymbolId, { fileId, startLine, startColumn, endLine, endColumn }); diff --git a/version.txt b/version.txt index aa30471..d689826 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -v2.db23.p2 +v2.db24.p0