diff --git a/bin/app/data/color_schemes/bad_rainbow.xml b/bin/app/data/color_schemes/bad_rainbow.xml index d8f0ff7e..8a81fbc2 100644 --- a/bin/app/data/color_schemes/bad_rainbow.xml +++ b/bin/app/data/color_schemes/bad_rainbow.xml @@ -143,7 +143,7 @@ - #D4D4D4 + #D4D4D4 #00A0B6 #00BCD6 #FF5961 diff --git a/bin/app/data/color_schemes/bright.xml b/bin/app/data/color_schemes/bright.xml index 337fa5a8..e5994328 100644 --- a/bin/app/data/color_schemes/bright.xml +++ b/bin/app/data/color_schemes/bright.xml @@ -143,7 +143,7 @@ - black + black #1B8856 #1B8856 #C1492D diff --git a/bin/app/data/color_schemes/dark.xml b/bin/app/data/color_schemes/dark.xml index e0157f6f..af191000 100644 --- a/bin/app/data/color_schemes/dark.xml +++ b/bin/app/data/color_schemes/dark.xml @@ -143,7 +143,7 @@ - #F7F7F7 + #F7F7F7 #1F9C62 #1F9C62 #D95233 diff --git a/bin/app/data/syntax_highlighting_rules/cpp.rules b/bin/app/data/syntax_highlighting_rules/cpp.rules new file mode 100644 index 00000000..9988ed9c --- /dev/null +++ b/bin/app/data/syntax_highlighting_rules/cpp.rules @@ -0,0 +1,169 @@ +[ + { + "type" : "quotation", + "patterns" : [ "\"([^\"]|\\\\.)*\"", "\'[^\']\'" ], + "priority" : true + }, + { + "type" : "comment", + "range" : { + "start" : "/\\*", + "end" : "\\*/" + }, + "priority" : true + }, + { + "type" : "keyword", + "patterns" : [ + "\\balignas\\b", + "\\balignof\\b", + "\\band\\b", + "\\band_eq\\b", + "\\basm\\b", + "\\bassert\\b", + "\\bauto\\b", + "\\bbitand\\b", + "\\bbitor\\b", + "\\bbreak\\b", + "\\bcase\\b", + "\\bcatch\\b", + "\\bcompl\\b", + "\\bcomplex\\b", + "\\bconst\\b", + "\\bconst_cast\\b", + "\\bconstexpr\\b", + "\\bcontinue\\b", + "\\bdecltype\\b", + "\\bdefault\\b", + "\\bdelete\\b", + "\\bdo\\b", + "\\bdynamic_cast\\b", + "\\belse\\b", + "\\bexplicit\\b", + "\\bexport\\b", + "\\bextern\\b", + "\\bfalse\\b", + "\\bfinal\\b", + "\\bfor\\b", + "\\bfriend\\b", + "\\bgoto\\b", + "\\bif\\b", + "\\bimaginary\\b", + "\\binline\\b", + "\\bmutable\\b", + "\\bnew\\b", + "\\bnoexcept\\b", + "\\bnoreturn\\b", + "\\bnot\\b", + "\\bnot_eq\\b", + "\\bNULL\\b", + "\\bnullptr\\b", + "\\boperator\\b", + "\\bor\\b", + "\\bor_eq\\b", + "\\boverride\\b", + "\\bprivate\\b", + "\\bprotected\\b", + "\\bpublic\\b", + "\\bregister\\b", + "\\breinterpret_cast\\b", + "\\brequires\\b", + "\\breturn\\b", + "\\bsignals\\b", + "\\bsizeof\\b", + "\\bslots\\b", + "\\bstatic\\b", + "\\bstatic_assert\\b", + "\\bstatic_cast\\b", + "\\bswitch\\b", + "\\btemplate\\b", + "\\bthis\\b", + "\\bthread_local\\b", + "\\bthrow\\b", + "\\bthrows\\b", + "\\btrue\\b", + "\\btry\\b", + "\\btypedef\\b", + "\\btypeid\\b", + "\\btypename\\b", + "\\busing\\b", + "\\bvirtual\\b", + "\\bvolatile\\b", + "\\bwhile\\b", + "\\bxor\\b", + "\\bxor_eq\\b" + ] + }, + { + "type" : "type", + "patterns" : [ + "\\bbool\\b", + "\\bchar16_t\\b", + "\\bchar32_t\\b", + "\\bchar\\b", + "\\bclass\\b", + "\\bdouble\\b", + "\\benum\\b", + "\\bfloat\\b", + "\\bint16_t\\b", + "\\bint32_t\\b", + "\\bint64_t\\b", + "\\bint8_t\\b", + "\\bint\\b", + "\\bint_fast16_t\\b", + "\\bint_fast32_t\\b", + "\\bint_fast64_t\\b", + "\\bint_fast8_t\\b", + "\\bint_least16_t\\b", + "\\bint_least32_t\\b", + "\\bint_least64_t\\b", + "\\bint_least8_t\\b", + "\\bintmax_t\\b", + "\\bintptr_t\\b", + "\\blong\\b", + "\\bnamespace\\b", + "\\bshort\\b", + "\\bsigned\\b", + "\\bsize_t\\b", + "\\bstruct\\b", + "\\buint16_t\\b", + "\\buint32_t\\b", + "\\buint64_t\\b", + "\\buint8_t\\b", + "\\buint_fast16_t\\b", + "\\buint_fast32_t\\b", + "\\buint_fast64_t\\b", + "\\buint_fast8_t\\b", + "\\buint_least16_t\\b", + "\\buint_least32_t\\b", + "\\buint_least64_t\\b", + "\\buint_least8_t\\b", + "\\buintmax_t\\b", + "\\buintptr_t\\b", + "\\bunion\\b", + "\\bunsigned\\b", + "\\bvoid\\b", + "\\bwchar_t\\b" + ] + }, + { + "type" : "directive", + "patterns" : [ "#[a-z]+\\b" ] + }, + { + "type" : "number", + "patterns" : [ "\\b[0-9]+\\b" ] + }, + { + "type" : "function", + "patterns" : [ "\\b[A-Za-z0-9_]+(?=\\()" ] + }, + { + "type" : "quotation", + "patterns" : [ " <[^<>\\s]*>$" ] + }, + { + "type" : "comment", + "patterns" : [ "//[^\n]*" ] + } +] \ No newline at end of file diff --git a/bin/app/data/syntax_highlighting_rules/java.rules b/bin/app/data/syntax_highlighting_rules/java.rules new file mode 100644 index 00000000..b38d71c8 --- /dev/null +++ b/bin/app/data/syntax_highlighting_rules/java.rules @@ -0,0 +1,95 @@ +[ + { + "type" : "quotation", + "patterns" : [ "\"([^\"]|\\\\.)*\"", "\'[^\']\'" ], + "priority" : true + }, + { + "type" : "comment", + "range" : { + "start" : "/\\*", + "end" : "\\*/" + }, + "priority" : true + }, + { + "type" : "keyword", + "patterns" : [ + "\\babstract\\b", + "\\bassert\\b", + "\\bbreak\\b", + "\\bcase\\b", + "\\bcatch\\b", + "\\bconst\\b", + "\\bcontinue\\b", + "\\bdefault\\b", + "\\bdo\\b", + "\\belse\\b", + "\\bextends\\b", + "\\bfalse\\b", + "\\bfinal\\b", + "\\bfinally\\b", + "\\bfor\\b", + "\\bfriend\\b", + "\\bgoto\\b", + "\\bif\\b", + "\\bimplements\\b", + "\\bimport\\b", + "\\binstanceof\\b", + "\\binterface\\b", + "\\bnative\\b", + "\\bnew\\b", + "\\bpackage\\b", + "\\bprivate\\b", + "\\bprotected\\b", + "\\bpublic\\b", + "\\breturn\\b", + "\\bstatic\\b", + "\\bstrictfp\\b", + "\\bsuper\\b", + "\\bswitch\\b", + "\\bsynchronized\\b", + "\\bthis\\b", + "\\bthrow\\b", + "\\bthrows\\b", + "\\btransient\\b", + "\\btrue\\b", + "\\btry\\b", + "\\bvolatile\\b", + "\\bwhile\\b" + ] + }, + { + "type" : "type", + "patterns" : [ + "\\bboolean\\b", + "\\bbyte\\b", + "\\bchar\\b", + "\\bclass\\b", + "\\bdouble\\b", + "\\benum\\b", + "\\bfloat\\b", + "\\bint\\b", + "\\blong\\b", + "\\bpackage\\b", + "\\bshort\\b", + "\\bvoid\\b" + ] + }, + { + "type" : "directive", + "patterns" : [ "@[A-Za-z0-9_]+" ] + }, + { + "type" : "number", + "patterns" : [ "\\b[0-9]+\\b" ] + }, + { + "type" : "function", + "patterns" : [ "\\b[A-Za-z0-9_]+(?=\\()" ] + }, + { + "type" : "comment", + "patterns" : [ "//[^\n]*" ] + } +] diff --git a/setup/MacOSX/bundle_install.sh.in b/setup/MacOSX/bundle_install.sh.in index 270cd407..9e9ed598 100755 --- a/setup/MacOSX/bundle_install.sh.in +++ b/setup/MacOSX/bundle_install.sh.in @@ -71,6 +71,7 @@ cp $INDEXER_NAME $INDEXER_PATH mkdir -p $RES_DIR/data cp -R ../../../bin/app/data/color_schemes $RES_DIR/data/color_schemes +cp -R ../../../bin/app/data/syntax_highlighting_rules $RES_DIR/data/syntax_highlighting_rules cp -R ../../../bin/app/data/fonts $RES_DIR/data/fonts cp -R ../../../bin/app/data/gui $RES_DIR/data/gui cp -R ../../../bin/app/data/java $RES_DIR/data/java diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index 6309ae9f..fe7b1aac 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -48,7 +48,7 @@ void CodeController::handleMessage(MessageActivateAll* message) statsSnippet.reduced = true; - statsSnippet.locationFile = std::make_shared(FilePath(), true, true, true); + statsSnippet.locationFile = std::make_shared(FilePath(), L"", true, true, true); std::vector description = getProjectDescription(statsSnippet.locationFile.get()); diff --git a/src/lib/data/access/StorageAccessProxy.cpp b/src/lib/data/access/StorageAccessProxy.cpp index 05a425a2..ebdac858 100644 --- a/src/lib/data/access/StorageAccessProxy.cpp +++ b/src/lib/data/access/StorageAccessProxy.cpp @@ -90,9 +90,9 @@ DEF_GETTER_2(getActiveTokenIdsForId, Id, Id*, std::vector, {}) DEF_GETTER_1(getNodeIdsForLocationIds, const std::vector&, std::vector, {}) DEF_GETTER_1(getSourceLocationsForTokenIds, const std::vector&, std::shared_ptr, std::make_shared()) DEF_GETTER_1(getSourceLocationsForLocationIds, const std::vector&, std::shared_ptr, std::make_shared()) -DEF_GETTER_1(getSourceLocationsForFile, const FilePath&, std::shared_ptr, std::make_shared(FilePath(), false, false, false)) -DEF_GETTER_3(getSourceLocationsForLinesInFile, const FilePath&, size_t, size_t, std::shared_ptr, std::make_shared(FilePath(), false, false, false)) -DEF_GETTER_2(getSourceLocationsOfTypeInFile, const FilePath&, LocationType, std::shared_ptr, std::make_shared(FilePath(), false, false, false)) +DEF_GETTER_1(getSourceLocationsForFile, const FilePath&, std::shared_ptr, std::make_shared(FilePath(), L"", false, false, false)) +DEF_GETTER_3(getSourceLocationsForLinesInFile, const FilePath&, size_t, size_t, std::shared_ptr, std::make_shared(FilePath(), L"", false, false, false)) +DEF_GETTER_2(getSourceLocationsOfTypeInFile, const FilePath&, LocationType, std::shared_ptr, std::make_shared(FilePath(), L"", false, false, false)) DEF_GETTER_2(getFileContent, const FilePath&, bool, std::shared_ptr, nullptr) DEF_GETTER_1(getFileInfoForFileId, Id, FileInfo, FileInfo()) DEF_GETTER_1(getFileInfoForFilePath, const FilePath&, FileInfo, FileInfo()) diff --git a/src/lib/data/location/SourceLocationCollection.cpp b/src/lib/data/location/SourceLocationCollection.cpp index ca2ca598..447b8556 100644 --- a/src/lib/data/location/SourceLocationCollection.cpp +++ b/src/lib/data/location/SourceLocationCollection.cpp @@ -81,8 +81,8 @@ SourceLocation* SourceLocationCollection::addSourceLocation( SourceLocation* SourceLocationCollection::addSourceLocationCopy(const SourceLocation* location) { SourceLocationFile* other = location->getSourceLocationFile(); - SourceLocationFile* file = - createSourceLocationFile(location->getFilePath(), other->isWhole(), other->isComplete(), other->isIndexed()); + SourceLocationFile* file = createSourceLocationFile( + location->getFilePath(), other->getLanguage(), other->isWhole(), other->isComplete(), other->isIndexed()); return file->addSourceLocationCopy(location); } @@ -92,7 +92,8 @@ void SourceLocationCollection::addSourceLocationCopies(const SourceLocationColle [this](std::shared_ptr otherFile) { SourceLocationFile* file = createSourceLocationFile( - otherFile->getFilePath(), otherFile->isWhole(), otherFile->isComplete(), otherFile->isIndexed()); + otherFile->getFilePath(), otherFile->getLanguage(), otherFile->isWhole(), otherFile->isComplete(), + otherFile->isIndexed()); otherFile->forEachSourceLocation( [file](SourceLocation* otherLocation) @@ -127,7 +128,7 @@ void SourceLocationCollection::forEachSourceLocation(std::function filePtr = - std::make_shared(filePath, isWhole, isComplete, isIndexed); + std::make_shared(filePath, language, isWhole, isComplete, isIndexed); m_files.emplace(filePath, filePtr); return filePtr.get(); } diff --git a/src/lib/data/location/SourceLocationCollection.h b/src/lib/data/location/SourceLocationCollection.h index bcc84db4..ab2d5dbd 100644 --- a/src/lib/data/location/SourceLocationCollection.h +++ b/src/lib/data/location/SourceLocationCollection.h @@ -43,7 +43,7 @@ public: private: SourceLocationFile* createSourceLocationFile( - const FilePath& filePath, bool isWhole = false, bool isComplete = false, bool isIndexed = false); + const FilePath& filePath, const std::wstring& language = L"", bool isWhole = false, bool isComplete = false, bool isIndexed = false); std::map> m_files; }; diff --git a/src/lib/data/location/SourceLocationFile.cpp b/src/lib/data/location/SourceLocationFile.cpp index 9c8ac9d3..c9bca811 100644 --- a/src/lib/data/location/SourceLocationFile.cpp +++ b/src/lib/data/location/SourceLocationFile.cpp @@ -1,7 +1,10 @@ #include "SourceLocationFile.h" -SourceLocationFile::SourceLocationFile(const FilePath& filePath, bool isWhole, bool isComplete, bool isIndexed) +SourceLocationFile::SourceLocationFile( + const FilePath& filePath, const std::wstring& language, bool isWhole, bool isComplete, bool isIndexed +) : m_filePath(filePath) + , m_language(language) , m_isWhole(isWhole) , m_isComplete(isComplete) , m_isIndexed(isIndexed) @@ -17,6 +20,16 @@ const FilePath& SourceLocationFile::getFilePath() const return m_filePath; } +void SourceLocationFile::setLanguage(const std::wstring& language) +{ + m_language = language; +} + +const std::wstring& SourceLocationFile::getLanguage() const +{ + return m_language; +} + void SourceLocationFile::setIsWhole(bool isWhole) { m_isWhole = isWhole; @@ -182,7 +195,7 @@ std::shared_ptr SourceLocationFile::getFilteredByLines( size_t firstLineNumber, size_t lastLineNumber) const { std::shared_ptr ret = - std::make_shared(getFilePath(), false, isComplete(), isIndexed()); + std::make_shared(getFilePath(), getLanguage(), false, isComplete(), isIndexed()); for (const std::shared_ptr& location : m_locations) { @@ -198,7 +211,7 @@ std::shared_ptr SourceLocationFile::getFilteredByLines( std::shared_ptr SourceLocationFile::getFilteredByType(LocationType type) const { std::shared_ptr ret = - std::make_shared(getFilePath(), false, isComplete(), isIndexed()); + std::make_shared(getFilePath(), getLanguage(), false, isComplete(), isIndexed()); for (const std::shared_ptr& location : m_locations) { @@ -220,7 +233,7 @@ std::shared_ptr SourceLocationFile::getFilteredByTypes(const } std::shared_ptr ret = - std::make_shared(getFilePath(), false, isComplete(), isIndexed()); + std::make_shared(getFilePath(), getLanguage(), false, isComplete(), isIndexed()); for (const std::shared_ptr& location : m_locations) { diff --git a/src/lib/data/location/SourceLocationFile.h b/src/lib/data/location/SourceLocationFile.h index fad5d84c..6718a6ff 100644 --- a/src/lib/data/location/SourceLocationFile.h +++ b/src/lib/data/location/SourceLocationFile.h @@ -23,11 +23,14 @@ public: } }; - SourceLocationFile(const FilePath& filePath, bool isWhole, bool isComplete, bool isIndexed); + SourceLocationFile(const FilePath& filePath, const std::wstring& language, bool isWhole, bool isComplete, bool isIndexed); virtual ~SourceLocationFile(); const FilePath& getFilePath() const; + void setLanguage(const std::wstring& language); + const std::wstring& getLanguage() const; + void setIsWhole(bool isWhole); bool isWhole() const; @@ -62,6 +65,7 @@ public: private: const FilePath m_filePath; + std::wstring m_language; bool m_isWhole; bool m_isComplete; bool m_isIndexed; diff --git a/src/lib/data/storage/PersistentStorage.cpp b/src/lib/data/storage/PersistentStorage.cpp index 39ad6c81..0e35e481 100644 --- a/src/lib/data/storage/PersistentStorage.cpp +++ b/src/lib/data/storage/PersistentStorage.cpp @@ -289,6 +289,7 @@ void PersistentStorage::clearCaches() m_fileNodePaths.clear(); m_fileNodeComplete.clear(); m_fileNodeIndexed.clear(); + m_fileNodeLanguage.clear(); m_symbolDefinitionKinds.clear(); m_hierarchyCache.clear(); @@ -1303,7 +1304,7 @@ std::shared_ptr PersistentStorage::getSourceLocationsF { TRACE(); - std::vector filePaths; + std::map filePaths; std::vector nonFileIds; for (const Id tokenId : tokenIds) @@ -1326,14 +1327,15 @@ std::shared_ptr PersistentStorage::getSourceLocationsF } else { - filePaths.push_back(path); + filePaths.emplace(tokenId, path); } } std::shared_ptr collection = std::make_shared(); - for (const FilePath& path : filePaths) + for (const std::pair& p : filePaths) { - collection->addSourceLocationFile(std::make_shared(path, true, false, false)); + collection->addSourceLocationFile( + std::make_shared(p.second, getFileNodeLanguage(p.first), true, false, false)); } if (nonFileIds.size()) @@ -1909,9 +1911,16 @@ TooltipSnippet PersistentStorage::getTooltipSnippetForNode(const StorageNode& no const NameHierarchy nameHierarchy = NameHierarchy::deserialize(node.serializedName); TooltipSnippet snippet; snippet.code = nameHierarchy.getQualifiedNameWithSignature(); - snippet.locationFile = std::make_shared( - FilePath(nameHierarchy.getDelimiter() == nameDelimiterTypeToString(NAME_DELIMITER_JAVA) ? L"main.java" : L"main.cpp"), - true, true, true); + snippet.locationFile = std::make_shared(FilePath(L"main.txt"), L"", true, true, true); + + // set file language + std::vector occurrences = m_sqliteIndexStorage.getOccurrencesForElementIds({ node.id }); + if (occurrences.size()) + { + const Id locationId = occurrences.front().sourceLocationId; + const Id fileId = m_sqliteIndexStorage.getFirstById(locationId).fileNodeId; + snippet.locationFile->setLanguage(getFileNodeLanguage(fileId)); + } if (nameHierarchy.hasSignature()) { @@ -2148,6 +2157,9 @@ TooltipInfo PersistentStorage::getTooltipInfoForSourceLocationIdsAndLocalSymbolI if (!locationIds.empty()) { + std::wstring fileLanguage = getFileNodeLanguage( + m_sqliteIndexStorage.getFirstById(locationIds.front()).fileNodeId); + const std::vector nodeIds = getNodeIdsForLocationIds(locationIds); for (const StorageNode& node : m_sqliteIndexStorage.getAllByIds(nodeIds)) @@ -2156,9 +2168,7 @@ TooltipInfo PersistentStorage::getTooltipInfoForSourceLocationIdsAndLocalSymbolI const NameHierarchy nameHierarchy = NameHierarchy::deserialize(node.serializedName); snippet.code = nameHierarchy.getQualifiedName(); - snippet.locationFile = std::make_shared( - FilePath(nameHierarchy.getDelimiter() == nameDelimiterTypeToString(NAME_DELIMITER_JAVA) ? L"main.java" : L"main.cpp"), - true, true, true); + snippet.locationFile = std::make_shared(FilePath(L"main.txt"), fileLanguage, true, true, true); snippet.locationFile->addSourceLocation( LOCATION_TOKEN, 0, std::vector(1, node.id), 1, 1, 1, snippet.code.size()); @@ -2177,7 +2187,7 @@ TooltipInfo PersistentStorage::getTooltipInfoForSourceLocationIdsAndLocalSymbolI TooltipSnippet snippet; snippet.code = L"local symbol"; - snippet.locationFile = std::make_shared(FilePath(L"main.cpp"), true, true, true); + snippet.locationFile = std::make_shared(FilePath(L"main.txt"), L"", true, true, true); snippet.locationFile->addSourceLocation( LOCATION_LOCAL_SYMBOL, 0, std::vector(1, id), 1, 1, 1, snippet.code.size()); @@ -2275,6 +2285,17 @@ bool PersistentStorage::getFileNodeIndexed(Id fileId) const return false; } +std::wstring PersistentStorage::getFileNodeLanguage(Id fileId) const +{ + auto it = m_fileNodeLanguage.find(fileId); + if (it != m_fileNodeLanguage.end()) + { + return it->second; + } + + return L""; +} + std::unordered_map> PersistentStorage::getFileIdToIncludingFileIdMap() const { std::unordered_map> fileIdToIncludingFileIdMap; @@ -2778,6 +2799,7 @@ void PersistentStorage::addCompleteFlagsToSourceLocationCollection(SourceLocatio Id fileId = getFileNodeId(file->getFilePath()); file->setIsComplete(getFileNodeComplete(fileId)); file->setIsIndexed(getFileNodeIndexed(fileId)); + file->setLanguage(getFileNodeLanguage(fileId)); } ); } @@ -2862,6 +2884,7 @@ void PersistentStorage::buildFilePathMaps() m_fileNodePaths.emplace(file.id, path); m_fileNodeComplete.emplace(file.id, file.complete); m_fileNodeIndexed.emplace(file.id, file.indexed); + m_fileNodeLanguage.emplace(file.id, file.languageIdentifier); if (!m_hasJavaFiles && path.extension() == L".java") { diff --git a/src/lib/data/storage/PersistentStorage.h b/src/lib/data/storage/PersistentStorage.h index 19af8222..48b13215 100644 --- a/src/lib/data/storage/PersistentStorage.h +++ b/src/lib/data/storage/PersistentStorage.h @@ -173,6 +173,7 @@ private: FilePath getFileNodePath(Id fileId) const; bool getFileNodeComplete(Id fileId) const; bool getFileNodeIndexed(Id fileId) const; + std::wstring getFileNodeLanguage(Id fileId) const; std::unordered_map> getFileIdToIncludingFileIdMap() const; std::unordered_map> getFileIdToIncludedFileIdMap() const; @@ -224,6 +225,7 @@ private: std::map m_fileNodePaths; std::map m_fileNodeComplete; std::map m_fileNodeIndexed; + std::map m_fileNodeLanguage; std::map m_symbolDefinitionKinds; std::map m_memberEdgeIdOrderMap; diff --git a/src/lib/data/storage/sqlite/SqliteIndexStorage.cpp b/src/lib/data/storage/sqlite/SqliteIndexStorage.cpp index 750df6ef..36362834 100644 --- a/src/lib/data/storage/sqlite/SqliteIndexStorage.cpp +++ b/src/lib/data/storage/sqlite/SqliteIndexStorage.cpp @@ -832,7 +832,7 @@ void SqliteIndexStorage::setNodeType(int type, Id nodeId) std::shared_ptr SqliteIndexStorage::getSourceLocationsForFile( const FilePath& filePath, const std::string& query) const { - std::shared_ptr ret = std::make_shared(filePath, true, false, false); + std::shared_ptr ret = std::make_shared(filePath, L"", true, false, false); const StorageFile file = getFileByPath(filePath.wstr()); if (file.id == 0) // early out @@ -840,6 +840,7 @@ std::shared_ptr SqliteIndexStorage::getSourceLocationsForFil return ret; } + ret->setLanguage(file.languageIdentifier); ret->setIsComplete(file.complete); ret->setIsIndexed(file.indexed); diff --git a/src/lib/utility/ResourcePaths.cpp b/src/lib/utility/ResourcePaths.cpp index 9d65b738..adfc6376 100644 --- a/src/lib/utility/ResourcePaths.cpp +++ b/src/lib/utility/ResourcePaths.cpp @@ -7,6 +7,11 @@ FilePath ResourcePaths::getColorSchemesPath() return AppPath::getAppPath().concatenate(L"data/color_schemes/"); } +FilePath ResourcePaths::getSyntaxHighlightingRulesPath() +{ + return AppPath::getAppPath().concatenate(L"data/syntax_highlighting_rules/"); +} + FilePath ResourcePaths::getFallbackPath() { return AppPath::getAppPath().concatenate(L"data/fallback/"); diff --git a/src/lib/utility/ResourcePaths.h b/src/lib/utility/ResourcePaths.h index b36eeb46..438aff2d 100644 --- a/src/lib/utility/ResourcePaths.h +++ b/src/lib/utility/ResourcePaths.h @@ -9,6 +9,7 @@ class ResourcePaths { public: static FilePath getColorSchemesPath(); + static FilePath getSyntaxHighlightingRulesPath(); static FilePath getFallbackPath(); static FilePath getFontsPath(); static FilePath getGuiPath(); diff --git a/src/lib_gui/qt/element/QtCodeField.cpp b/src/lib_gui/qt/element/QtCodeField.cpp index 92630252..8d2f1bf2 100644 --- a/src/lib_gui/qt/element/QtCodeField.cpp +++ b/src/lib_gui/qt/element/QtCodeField.cpp @@ -87,14 +87,7 @@ QtCodeField::QtCodeField( createAnnotations(locationFile); - FilePath path = locationFile->getFilePath(); - LanguageType language = LANGUAGE_UNKNOWN; - if (!path.empty()) - { - language = (path.extension() == L".java" ? LANGUAGE_JAVA : LANGUAGE_CPP); - } - - m_highlighter = std::make_shared(document(), language); + m_highlighter = std::make_shared(document(), locationFile->getLanguage()); m_highlighter->highlightDocument(); ApplicationSettings* appSettings = ApplicationSettings::getInstance().get(); diff --git a/src/lib_gui/qt/element/QtCodeSnippet.cpp b/src/lib_gui/qt/element/QtCodeSnippet.cpp index ab388801..4919ea14 100644 --- a/src/lib_gui/qt/element/QtCodeSnippet.cpp +++ b/src/lib_gui/qt/element/QtCodeSnippet.cpp @@ -19,8 +19,8 @@ QtCodeSnippet* QtCodeSnippet::merged( SourceLocationFile* aFile = a->m_codeArea->getSourceLocationFile().get(); SourceLocationFile* bFile = b->m_codeArea->getSourceLocationFile().get(); - std::shared_ptr locationFile = - std::make_shared(aFile->getFilePath(), aFile->isWhole(), aFile->isComplete(), aFile->isIndexed()); + std::shared_ptr locationFile = std::make_shared( + aFile->getFilePath(), aFile->getLanguage(), aFile->isWhole(), aFile->isComplete(), aFile->isIndexed()); aFile->forEachSourceLocation( [&locationFile](SourceLocation* loc) diff --git a/src/lib_gui/qt/element/QtNewsWidget.cpp b/src/lib_gui/qt/element/QtNewsWidget.cpp index eb4bcee1..31375338 100644 --- a/src/lib_gui/qt/element/QtNewsWidget.cpp +++ b/src/lib_gui/qt/element/QtNewsWidget.cpp @@ -102,6 +102,11 @@ void QtNewsWidget::updateNews() size_t itemNum = 0; for (QJsonValueRef value : doc.array()) { + if (!value.isObject()) + { + continue; + } + itemNum++; QJsonObject newsItem = value.toObject(); diff --git a/src/lib_gui/qt/utility/QtHighlighter.cpp b/src/lib_gui/qt/utility/QtHighlighter.cpp index bc87cce0..ea50ddc9 100644 --- a/src/lib_gui/qt/utility/QtHighlighter.cpp +++ b/src/lib_gui/qt/utility/QtHighlighter.cpp @@ -1,112 +1,141 @@ #include "QtHighlighter.h" +#include +#include +#include #include #include #include #include "ColorScheme.h" +#include "FileSystem.h" +#include "ResourcePaths.h" +#include "TextAccess.h" #include "tracing.h" #include "utility.h" -QVector QtHighlighter::s_highlightingRules; -QVector QtHighlighter::s_highlightingRulesCpp; -QVector QtHighlighter::s_highlightingRulesJava; -QtHighlighter::HighlightingRule QtHighlighter::s_stringQuotationRule; -QtHighlighter::HighlightingRule QtHighlighter::s_charQuotationRule; -QtHighlighter::HighlightingRule QtHighlighter::s_commentRule; +std::map> QtHighlighter::s_highlightingRules; QTextCharFormat QtHighlighter::s_textFormat; -void QtHighlighter::createHighlightingRules() +std::string QtHighlighter::highlightTypeToString(QtHighlighter::HighlightType type) { - QStringList keywordPatternsCpp; - keywordPatternsCpp - << "alignas" << "alignof" << "and" << "and_eq" << "asm" << "assert" << "auto" << "bitand" << "bitor" - << "break" << "case" << "catch" << "compl" << "complex" << "const" << "constexpr" << "const_cast" - << "continue" << "decltype" << "default" << "delete" << "do" << "dynamic_cast" << "else" << "explicit" - << "export" << "extern" << "false" << "final" << "for" << "friend" << "goto" << "if" << "imaginary" - << "inline" << "mutable" << "new" << "noexcept" << "not" << "not_eq" << "noreturn" << "NULL" << "nullptr" - << "operator" << "or" << "or_eq" << "override" << "private" << "protected" << "public" << "register" - << "reinterpret_cast" << "requires" << "return" << "signals" << "sizeof" << "slots" << "static" - << "static_assert" << "static_cast" << "switch" << "template" << "this" << "thread_local" << "throw" - << "throws" << "true" << "try" << "typedef" << "typeid" << "typename" << "using" << "virtual" << "volatile" - << "while" << "xor" << "xor_eq"; + switch (type) + { + case HighlightType::COMMENT: return "comment"; + case HighlightType::DIRECTIVE: return "directive"; + case HighlightType::FUNCTION: return "function"; + case HighlightType::KEYWORD: return "keyword"; + case HighlightType::NUMBER: return "number"; + case HighlightType::QUOTATION: return "quotation"; + case HighlightType::TEXT: return "text"; + case HighlightType::TYPE: return "type"; + } + return "text"; +} - QStringList keywordPatternsJava; - keywordPatternsJava - << "abstract" << "assert" << "break" << "case" << "catch" << "const" << "continue" << "default" - << "do" << "else" << "extends" << "false" << "final" << "finally" << "for" - << "friend" << "goto" << "if" << "implements" << "import" << "instanceof" << "interface" << "native" - << "new" << "package" << "private" << "protected" << "public" << "return" << "static" << "strictfp" - << "super" << "switch" << "synchronized" << "this" << "true" << "throw" << "throws" << "transient" - << "try" << "volatile" << "while"; +QtHighlighter::HighlightType QtHighlighter::highlightTypeFromString(const std::string typeStr) +{ + const std::array types = { + HighlightType::COMMENT, + HighlightType::DIRECTIVE, + HighlightType::FUNCTION, + HighlightType::KEYWORD, + HighlightType::NUMBER, + HighlightType::QUOTATION, + HighlightType::TEXT, + HighlightType::TYPE + }; - QStringList typePatternsCpp; - typePatternsCpp - << "bool" << "char" << "char16_t" << "char32_t" << "class" << "double" << "enum" << "float" << "int" - << "long" << "namespace" << "short" << "signed" << "size_t" << "struct" << "union" << "unsigned" << "void" - << "wchar_t"; + for (HighlightType type : types) + { + if (typeStr == highlightTypeToString(type)) + { + return type; + } + } - QStringList typePatternsJava; - typePatternsJava - << "boolean" << "byte" << "char" << "class" << "double" << "enum" << "float" << "int" << "long" << "package" - << "short" << "void"; - - QRegExp directiveRegExp = QRegExp("#[a-z]+\\b"); - QRegExp annotationRegExp = QRegExp("@[A-Za-z0-9_]+"); - QRegExp numberRegExp = QRegExp("\\b[0-9]+\\b"); - QRegExp functionRegExp = QRegExp("\\b[A-Za-z0-9_]+(?=\\()"); - QRegExp stringQuotationRegExp = QRegExp("\"([^\"]|\\\\.)*\""); - QRegExp charQuotationRegExp = QRegExp("\'[^\']\'"); - QRegExp tagQuotationRegExp = QRegExp(" <[^<>\\s]*>$"); - QRegExp commentRegExp = QRegExp("//[^\n]*"); + return HighlightType::TEXT; +} +void QtHighlighter::loadHighlightingRules() +{ ColorScheme* scheme = ColorScheme::getInstance().get(); - s_textFormat.setForeground(QColor(scheme->getSyntaxColor("normal").c_str())); + std::map ruleTypeColors; + const std::array types = { + HighlightType::COMMENT, + HighlightType::DIRECTIVE, + HighlightType::FUNCTION, + HighlightType::KEYWORD, + HighlightType::NUMBER, + HighlightType::QUOTATION, + HighlightType::TEXT, + HighlightType::TYPE + }; - QColor directiveColor(scheme->getSyntaxColor("directive").c_str()); - QColor annotationColor = directiveColor; - QColor keywordColor(scheme->getSyntaxColor("keyword").c_str()); - QColor typeColor(scheme->getSyntaxColor("type").c_str()); - QColor numberColor(scheme->getSyntaxColor("number").c_str()); - QColor functionColor(scheme->getSyntaxColor("function").c_str()); - QColor quotationColor(scheme->getSyntaxColor("quotation").c_str()); - QColor commentColor(scheme->getSyntaxColor("comment").c_str()); - - s_highlightingRules.clear(); - s_highlightingRules.append(HighlightingRule(directiveColor, directiveRegExp)); - s_highlightingRules.append(HighlightingRule(numberColor, numberRegExp)); - s_highlightingRules.append(HighlightingRule(functionColor, functionRegExp)); - s_highlightingRules.append(HighlightingRule(annotationColor, annotationRegExp)); - s_highlightingRules.append(HighlightingRule(quotationColor, tagQuotationRegExp)); - - s_highlightingRulesCpp.clear(); - - foreach (const QString &pattern, keywordPatternsCpp) + for (HighlightType type : types) { - s_highlightingRulesCpp.append(HighlightingRule(keywordColor, QRegExp("\\b" + pattern + "\\b"))); + ruleTypeColors.emplace(type, QColor(scheme->getSyntaxColor(highlightTypeToString(type)).c_str())); } - foreach (const QString &pattern, typePatternsCpp) + s_textFormat.setForeground(ruleTypeColors[HighlightType::TEXT]); + + for (const FilePath path : + FileSystem::getFilePathsFromDirectory(ResourcePaths::getSyntaxHighlightingRulesPath(), { L".rules" })) { - s_highlightingRulesCpp.append(HighlightingRule(typeColor, QRegExp("\\b" + pattern + "\\b"))); + std::wstring language = path.withoutExtension().fileName(); + + std::shared_ptr textAccess = TextAccess::createFromFile(path); + + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(QString::fromStdString(textAccess->getText()).toUtf8(), &error); + if (doc.isNull() || !doc.isArray()) + { + LOG_ERROR_STREAM(<< "Highlinghting rules in \"" << path.str() << "\" couldn't be parsed as JSON: " + "offset " << error.offset << " - " << error.errorString().toStdString()); + continue; + } + + std::vector rules; + + for (QJsonValueRef value : doc.array()) + { + if (!value.isObject()) + { + continue; + } + + QJsonObject ruleObj = value.toObject(); + + HighlightType type = highlightTypeFromString(ruleObj.value("type").toString().toStdString()); + + auto colorIt = ruleTypeColors.find(type); + if (colorIt == ruleTypeColors.end()) + { + continue; + } + + bool priority = ruleObj.value("priority").toBool(); + + QJsonArray patterns = ruleObj.value("patterns").toArray(); + for (QJsonValueRef pattern : patterns) + { + if (pattern.isString()) + { + rules.push_back(HighlightingRule(type, colorIt->second, QRegExp(pattern.toString()), priority)); + } + } + + QJsonObject range = ruleObj.value("range").toObject(); + if (!range.empty()) + { + rules.push_back(HighlightingRule(type, colorIt->second, QRegExp(range.value("start").toString()), priority, true)); + rules.push_back(HighlightingRule(type, colorIt->second, QRegExp(range.value("end").toString()), priority, true)); + } + } + + s_highlightingRules.emplace(language, rules); } - - s_highlightingRulesJava.clear(); - - foreach (const QString &pattern, keywordPatternsJava) - { - s_highlightingRulesJava.append(HighlightingRule(keywordColor, QRegExp("\\b" + pattern + "\\b"))); - } - - foreach (const QString &pattern, typePatternsJava) - { - s_highlightingRulesJava.append(HighlightingRule(typeColor, QRegExp("\\b" + pattern + "\\b"))); - } - - s_stringQuotationRule = HighlightingRule(quotationColor, stringQuotationRegExp); - s_charQuotationRule = HighlightingRule(quotationColor, charQuotationRegExp); - s_commentRule = HighlightingRule(commentColor, commentRegExp); } void QtHighlighter::clearHighlightingRules() @@ -114,30 +143,19 @@ void QtHighlighter::clearHighlightingRules() s_highlightingRules.clear(); } -QtHighlighter::QtHighlighter(QTextDocument *document, LanguageType language) +QtHighlighter::QtHighlighter(QTextDocument *document, const std::wstring& language) : m_document(document) - , m_language(language) { if (!s_highlightingRules.size()) { - createHighlightingRules(); + loadHighlightingRules(); } - if (m_language == LANGUAGE_UNKNOWN) + const auto it = s_highlightingRules.find(language); + if (it != s_highlightingRules.end()) { - return; + m_highlightingRules = it->second; } - - if (m_language == LANGUAGE_JAVA) - { - m_highlightingRules = s_highlightingRulesJava; - } - else - { - m_highlightingRules = s_highlightingRulesCpp; - } - - m_highlightingRules.append(s_highlightingRules); } void QtHighlighter::highlightDocument() @@ -163,12 +181,20 @@ void QtHighlighter::highlightDocument() m_highlightedLines.clear(); m_highlightedLines.resize(document()->blockCount(), false); - if (m_language == LANGUAGE_UNKNOWN) + if (m_highlightingRules.empty()) { return; } - createRanges(doc, s_stringQuotationRule, s_charQuotationRule); + std::vector quotationRules; + for (const HighlightingRule& rule : m_highlightingRules) + { + if (rule.priority && rule.type == HighlightType::QUOTATION) + { + quotationRules.emplace_back(rule); + } + } + createRanges(doc, quotationRules); } void QtHighlighter::highlightRange(int startLine, int endLine) @@ -197,6 +223,21 @@ void QtHighlighter::highlightRange(int startLine, int endLine) QTextBlock start = doc->findBlockByLineNumber(startLine); QTextBlock end = doc->findBlockByLineNumber(endLine + 1); + const HighlightingRule* singleLineCommentRule = nullptr; + const HighlightingRule* quotationRule = nullptr; + + for (const HighlightingRule& rule : m_highlightingRules) + { + if (rule.type == HighlightType::COMMENT && !rule.multiLine) + { + singleLineCommentRule = &rule; + } + else if (rule.type == HighlightType::QUOTATION) + { + quotationRule = &rule; + } + } + int index = startLine; for (QTextBlock it = start; it != end; it = it.next()) { @@ -204,17 +245,23 @@ void QtHighlighter::highlightRange(int startLine, int endLine) { applyFormat(it.position(), it.position() + it.length() - 1, s_textFormat); - if (m_language != LANGUAGE_UNKNOWN) + for (const HighlightingRule &rule : m_highlightingRules) { - foreach (const HighlightingRule &rule, m_highlightingRules) + if (!rule.priority && rule.type != HighlightType::COMMENT) { formatBlockForRule(it, rule); } + } - formatBlockIfInRange(it, s_stringQuotationRule.format, &m_quotationRanges); - formatBlockIfInRange(it, s_charQuotationRule.format, &m_quotationRanges); - formatBlockForRule(it, s_commentRule, &m_quotationRanges); - formatBlockIfInRange(it, s_commentRule.format, &m_multiLineCommentRanges); + if (quotationRule) + { + formatBlockIfInRange(it, quotationRule->format, &m_quotationRanges); + } + + if (singleLineCommentRule) + { + formatBlockForRule(it, *singleLineCommentRule, &m_quotationRanges); + formatBlockIfInRange(it, singleLineCommentRule->format, &m_multiLineCommentRanges); } } index++; @@ -253,15 +300,17 @@ QTextCharFormat QtHighlighter::getFormat(int startPosition, int endPosition) con } void QtHighlighter::createRanges( - QTextDocument* doc, const HighlightingRule& stringRule, const HighlightingRule& charRule) + QTextDocument* doc, const std::vector& quotationRules) { m_quotationRanges.clear(); m_multiLineCommentRanges.clear(); for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next()) { - utility::append(m_quotationRanges, getRangesForRule(it, stringRule)); - utility::append(m_quotationRanges, getRangesForRule(it, charRule)); + for (const HighlightingRule& rule : quotationRules) + { + utility::append(m_quotationRanges, getRangesForRule(it, rule)); + } } m_multiLineCommentRanges = createMultiLineCommentRanges(doc, &m_quotationRanges); @@ -270,32 +319,62 @@ void QtHighlighter::createRanges( std::vector> QtHighlighter::createMultiLineCommentRanges( QTextDocument* doc, std::vector>* ranges) { - QRegExp commentStartExpression = QRegExp("/\\*"); - QRegExp commentEndExpression = QRegExp("\\*/"); + const HighlightingRule* multiLineCommentStartRule = nullptr; + const HighlightingRule* multiLineCommentEndRule = nullptr; + const HighlightingRule* singleLineCommentRule = nullptr; + + for (const HighlightingRule& rule : m_highlightingRules) + { + if (rule.type == HighlightType::COMMENT) + { + if (rule.priority && rule.multiLine) + { + if (!multiLineCommentStartRule) + { + multiLineCommentStartRule = &rule; + } + else if (!multiLineCommentEndRule) + { + multiLineCommentEndRule = &rule; + } + } + else if (!rule.multiLine) + { + singleLineCommentRule = &rule; + } + } + } + + std::vector> multiLineCommentRanges; + if (!multiLineCommentStartRule || !multiLineCommentEndRule) + { + return multiLineCommentRanges; + } QTextCursor cursorStart(doc); QTextCursor cursorEnd(doc); - std::vector> multiLineCommentRanges; - while (true) { while (true) { - cursorStart = document()->find(commentStartExpression, cursorStart); + cursorStart = document()->find(multiLineCommentStartRule->pattern, cursorStart); if (cursorStart.isNull()) { break; } // ignore if within single line comment - QTextCursor inlineCommentStart = document()->find(s_commentRule.pattern, QTextCursor(cursorStart.block())); - if (!inlineCommentStart.isNull() && - inlineCommentStart.blockNumber() == cursorStart.blockNumber() && - inlineCommentStart.selectionStart() < cursorStart.selectionStart()) + if (singleLineCommentRule) { - cursorStart = QTextCursor(inlineCommentStart.block().next()); - continue; + QTextCursor inlineCommentStart = document()->find(singleLineCommentRule->pattern, QTextCursor(cursorStart.block())); + if (!inlineCommentStart.isNull() && + inlineCommentStart.blockNumber() == cursorStart.blockNumber() && + inlineCommentStart.selectionStart() < cursorStart.selectionStart()) + { + cursorStart = QTextCursor(inlineCommentStart.block().next()); + continue; + } } if (!isInRange(cursorStart.selectionEnd(), *ranges)) @@ -314,7 +393,7 @@ std::vector> QtHighlighter::createMultiLineCommentRanges( break; } - cursorEnd = document()->find(commentEndExpression, cursorStart); + cursorEnd = document()->find(multiLineCommentEndRule->pattern, cursorStart); if (cursorEnd.isNull()) { break; @@ -331,10 +410,15 @@ QtHighlighter::HighlightingRule::HighlightingRule() { } -QtHighlighter::HighlightingRule::HighlightingRule(const QColor& color, const QRegExp& regExp) +QtHighlighter::HighlightingRule::HighlightingRule( + HighlightType type, const QColor& color, const QRegExp& regExp, bool priority, bool multiLine +) + : type(type) + , pattern(regExp) + , priority(priority) + , multiLine(multiLine) { format.setForeground(color); - pattern = regExp; } bool QtHighlighter::isInRange(int pos, const std::vector>& ranges) const diff --git a/src/lib_gui/qt/utility/QtHighlighter.h b/src/lib_gui/qt/utility/QtHighlighter.h index 785f874b..c26218b6 100644 --- a/src/lib_gui/qt/utility/QtHighlighter.h +++ b/src/lib_gui/qt/utility/QtHighlighter.h @@ -3,18 +3,31 @@ #include -#include "LanguageType.h" - class QTextBlock; class QTextDocument; class QtHighlighter { public: - static void createHighlightingRules(); + enum class HighlightType + { + COMMENT, + DIRECTIVE, + FUNCTION, + KEYWORD, + NUMBER, + QUOTATION, + TEXT, + TYPE + }; + + static std::string highlightTypeToString(HighlightType type); + static HighlightType highlightTypeFromString(const std::string typeStr); + + static void loadHighlightingRules(); static void clearHighlightingRules(); - QtHighlighter(QTextDocument *parent, LanguageType language); + QtHighlighter(QTextDocument *parent, const std::wstring& language); ~QtHighlighter() = default; void highlightDocument(); @@ -30,13 +43,16 @@ private: struct HighlightingRule { HighlightingRule(); - HighlightingRule(const QColor& color, const QRegExp& regExp); + HighlightingRule(HighlightType type, const QColor& color, const QRegExp& regExp, bool priority, bool multiLine = false); + HighlightType type = HighlightType::TEXT; QRegExp pattern; QTextCharFormat format; + bool priority = false; + bool multiLine = false; }; - void createRanges(QTextDocument* doc, const HighlightingRule& stringRule, const HighlightingRule& charRule); + void createRanges(QTextDocument* doc, const std::vector& quotationRules); std::vector> createMultiLineCommentRanges( QTextDocument* doc, std::vector>* ranges); @@ -50,19 +66,12 @@ private: QTextDocument* document() const; - static QVector s_highlightingRules; - static QVector s_highlightingRulesCpp; - static QVector s_highlightingRulesJava; - static HighlightingRule s_stringQuotationRule; - static HighlightingRule s_charQuotationRule; - static HighlightingRule s_commentRule; + static std::map> s_highlightingRules; static QTextCharFormat s_textFormat; QTextDocument* m_document; - LanguageType m_language; - - QVector m_highlightingRules; + std::vector m_highlightingRules; std::vector> m_quotationRanges; std::vector> m_multiLineCommentRanges; std::vector m_highlightedLines;