ui: Extracted syntax highlighting rules for java and cpp to files

* pass file language from storage to code view
* load syntax highlighting rules files from install directory "syntax_highlighting_rules"
* files must be named <language_identifier>.rules to make syntax highlighting work
This commit is contained in:
Eberhard Graether
2018-12-16 22:59:07 +01:00
parent a45dcb8a01
commit 1dabbab599
22 changed files with 586 additions and 180 deletions
+1 -1
View File
@@ -143,7 +143,7 @@
</line_number>
<syntax>
<normal>#D4D4D4</normal>
<text>#D4D4D4</text>
<directive>#00A0B6</directive>
<keyword>#00BCD6</keyword>
<type>#FF5961</type>
+1 -1
View File
@@ -143,7 +143,7 @@
</line_number>
<syntax>
<normal>black</normal>
<text>black</text>
<directive>#1B8856</directive>
<keyword>#1B8856</keyword>
<type>#C1492D</type>
+1 -1
View File
@@ -143,7 +143,7 @@
</line_number>
<syntax>
<normal>#F7F7F7</normal>
<text>#F7F7F7</text>
<directive>#1F9C62</directive>
<keyword>#1F9C62</keyword>
<type>#D95233</type>
@@ -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]*" ]
}
]
@@ -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]*" ]
}
]
+1
View File
@@ -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
@@ -48,7 +48,7 @@ void CodeController::handleMessage(MessageActivateAll* message)
statsSnippet.reduced = true;
statsSnippet.locationFile = std::make_shared<SourceLocationFile>(FilePath(), true, true, true);
statsSnippet.locationFile = std::make_shared<SourceLocationFile>(FilePath(), L"", true, true, true);
std::vector<std::string> description = getProjectDescription(statsSnippet.locationFile.get());
+3 -3
View File
@@ -90,9 +90,9 @@ DEF_GETTER_2(getActiveTokenIdsForId, Id, Id*, std::vector<Id>, {})
DEF_GETTER_1(getNodeIdsForLocationIds, const std::vector<Id>&, std::vector<Id>, {})
DEF_GETTER_1(getSourceLocationsForTokenIds, const std::vector<Id>&, std::shared_ptr<SourceLocationCollection>, std::make_shared<SourceLocationCollection>())
DEF_GETTER_1(getSourceLocationsForLocationIds, const std::vector<Id>&, std::shared_ptr<SourceLocationCollection>, std::make_shared<SourceLocationCollection>())
DEF_GETTER_1(getSourceLocationsForFile, const FilePath&, std::shared_ptr<SourceLocationFile>, std::make_shared<SourceLocationFile>(FilePath(), false, false, false))
DEF_GETTER_3(getSourceLocationsForLinesInFile, const FilePath&, size_t, size_t, std::shared_ptr<SourceLocationFile>, std::make_shared<SourceLocationFile>(FilePath(), false, false, false))
DEF_GETTER_2(getSourceLocationsOfTypeInFile, const FilePath&, LocationType, std::shared_ptr<SourceLocationFile>, std::make_shared<SourceLocationFile>(FilePath(), false, false, false))
DEF_GETTER_1(getSourceLocationsForFile, const FilePath&, std::shared_ptr<SourceLocationFile>, std::make_shared<SourceLocationFile>(FilePath(), L"", false, false, false))
DEF_GETTER_3(getSourceLocationsForLinesInFile, const FilePath&, size_t, size_t, std::shared_ptr<SourceLocationFile>, std::make_shared<SourceLocationFile>(FilePath(), L"", false, false, false))
DEF_GETTER_2(getSourceLocationsOfTypeInFile, const FilePath&, LocationType, std::shared_ptr<SourceLocationFile>, std::make_shared<SourceLocationFile>(FilePath(), L"", false, false, false))
DEF_GETTER_2(getFileContent, const FilePath&, bool, std::shared_ptr<TextAccess>, nullptr)
DEF_GETTER_1(getFileInfoForFileId, Id, FileInfo, FileInfo())
DEF_GETTER_1(getFileInfoForFilePath, const FilePath&, FileInfo, FileInfo())
@@ -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<SourceLocationFile> 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<void(SourceLo
}
SourceLocationFile* SourceLocationCollection::createSourceLocationFile(
const FilePath& filePath, bool isWhole, bool isComplete, bool isIndexed)
const FilePath& filePath, const std::wstring& language, bool isWhole, bool isComplete, bool isIndexed)
{
SourceLocationFile* file = getSourceLocationFileByPath(filePath).get();
if (file)
@@ -136,7 +137,7 @@ SourceLocationFile* SourceLocationCollection::createSourceLocationFile(
}
std::shared_ptr<SourceLocationFile> filePtr =
std::make_shared<SourceLocationFile>(filePath, isWhole, isComplete, isIndexed);
std::make_shared<SourceLocationFile>(filePath, language, isWhole, isComplete, isIndexed);
m_files.emplace(filePath, filePtr);
return filePtr.get();
}
@@ -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<FilePath, std::shared_ptr<SourceLocationFile>> m_files;
};
+17 -4
View File
@@ -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> SourceLocationFile::getFilteredByLines(
size_t firstLineNumber, size_t lastLineNumber) const
{
std::shared_ptr<SourceLocationFile> ret =
std::make_shared<SourceLocationFile>(getFilePath(), false, isComplete(), isIndexed());
std::make_shared<SourceLocationFile>(getFilePath(), getLanguage(), false, isComplete(), isIndexed());
for (const std::shared_ptr<SourceLocation>& location : m_locations)
{
@@ -198,7 +211,7 @@ std::shared_ptr<SourceLocationFile> SourceLocationFile::getFilteredByLines(
std::shared_ptr<SourceLocationFile> SourceLocationFile::getFilteredByType(LocationType type) const
{
std::shared_ptr<SourceLocationFile> ret =
std::make_shared<SourceLocationFile>(getFilePath(), false, isComplete(), isIndexed());
std::make_shared<SourceLocationFile>(getFilePath(), getLanguage(), false, isComplete(), isIndexed());
for (const std::shared_ptr<SourceLocation>& location : m_locations)
{
@@ -220,7 +233,7 @@ std::shared_ptr<SourceLocationFile> SourceLocationFile::getFilteredByTypes(const
}
std::shared_ptr<SourceLocationFile> ret =
std::make_shared<SourceLocationFile>(getFilePath(), false, isComplete(), isIndexed());
std::make_shared<SourceLocationFile>(getFilePath(), getLanguage(), false, isComplete(), isIndexed());
for (const std::shared_ptr<SourceLocation>& location : m_locations)
{
+5 -1
View File
@@ -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;
+34 -11
View File
@@ -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<SourceLocationCollection> PersistentStorage::getSourceLocationsF
{
TRACE();
std::vector<FilePath> filePaths;
std::map<Id, FilePath> filePaths;
std::vector<Id> nonFileIds;
for (const Id tokenId : tokenIds)
@@ -1326,14 +1327,15 @@ std::shared_ptr<SourceLocationCollection> PersistentStorage::getSourceLocationsF
}
else
{
filePaths.push_back(path);
filePaths.emplace(tokenId, path);
}
}
std::shared_ptr<SourceLocationCollection> collection = std::make_shared<SourceLocationCollection>();
for (const FilePath& path : filePaths)
for (const std::pair<Id, FilePath>& p : filePaths)
{
collection->addSourceLocationFile(std::make_shared<SourceLocationFile>(path, true, false, false));
collection->addSourceLocationFile(
std::make_shared<SourceLocationFile>(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<SourceLocationFile>(
FilePath(nameHierarchy.getDelimiter() == nameDelimiterTypeToString(NAME_DELIMITER_JAVA) ? L"main.java" : L"main.cpp"),
true, true, true);
snippet.locationFile = std::make_shared<SourceLocationFile>(FilePath(L"main.txt"), L"", true, true, true);
// set file language
std::vector<StorageOccurrence> occurrences = m_sqliteIndexStorage.getOccurrencesForElementIds({ node.id });
if (occurrences.size())
{
const Id locationId = occurrences.front().sourceLocationId;
const Id fileId = m_sqliteIndexStorage.getFirstById<StorageSourceLocation>(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<StorageSourceLocation>(locationIds.front()).fileNodeId);
const std::vector<Id> nodeIds = getNodeIdsForLocationIds(locationIds);
for (const StorageNode& node : m_sqliteIndexStorage.getAllByIds<StorageNode>(nodeIds))
@@ -2156,9 +2168,7 @@ TooltipInfo PersistentStorage::getTooltipInfoForSourceLocationIdsAndLocalSymbolI
const NameHierarchy nameHierarchy = NameHierarchy::deserialize(node.serializedName);
snippet.code = nameHierarchy.getQualifiedName();
snippet.locationFile = std::make_shared<SourceLocationFile>(
FilePath(nameHierarchy.getDelimiter() == nameDelimiterTypeToString(NAME_DELIMITER_JAVA) ? L"main.java" : L"main.cpp"),
true, true, true);
snippet.locationFile = std::make_shared<SourceLocationFile>(FilePath(L"main.txt"), fileLanguage, true, true, true);
snippet.locationFile->addSourceLocation(
LOCATION_TOKEN, 0, std::vector<Id>(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<SourceLocationFile>(FilePath(L"main.cpp"), true, true, true);
snippet.locationFile = std::make_shared<SourceLocationFile>(FilePath(L"main.txt"), L"", true, true, true);
snippet.locationFile->addSourceLocation(
LOCATION_LOCAL_SYMBOL, 0, std::vector<Id>(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<Id, std::set<Id>> PersistentStorage::getFileIdToIncludingFileIdMap() const
{
std::unordered_map<Id, std::set<Id>> 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")
{
+2
View File
@@ -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<Id, std::set<Id>> getFileIdToIncludingFileIdMap() const;
std::unordered_map<Id, std::set<Id>> getFileIdToIncludedFileIdMap() const;
@@ -224,6 +225,7 @@ private:
std::map<Id, FilePath> m_fileNodePaths;
std::map<Id, bool> m_fileNodeComplete;
std::map<Id, bool> m_fileNodeIndexed;
std::map<Id, std::wstring> m_fileNodeLanguage;
std::map<Id, DefinitionKind> m_symbolDefinitionKinds;
std::map<Id, Id> m_memberEdgeIdOrderMap;
@@ -832,7 +832,7 @@ void SqliteIndexStorage::setNodeType(int type, Id nodeId)
std::shared_ptr<SourceLocationFile> SqliteIndexStorage::getSourceLocationsForFile(
const FilePath& filePath, const std::string& query) const
{
std::shared_ptr<SourceLocationFile> ret = std::make_shared<SourceLocationFile>(filePath, true, false, false);
std::shared_ptr<SourceLocationFile> ret = std::make_shared<SourceLocationFile>(filePath, L"", true, false, false);
const StorageFile file = getFileByPath(filePath.wstr());
if (file.id == 0) // early out
@@ -840,6 +840,7 @@ std::shared_ptr<SourceLocationFile> SqliteIndexStorage::getSourceLocationsForFil
return ret;
}
ret->setLanguage(file.languageIdentifier);
ret->setIsComplete(file.complete);
ret->setIsIndexed(file.indexed);
+5
View File
@@ -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/");
+1
View File
@@ -9,6 +9,7 @@ class ResourcePaths
{
public:
static FilePath getColorSchemesPath();
static FilePath getSyntaxHighlightingRulesPath();
static FilePath getFallbackPath();
static FilePath getFontsPath();
static FilePath getGuiPath();
+1 -8
View File
@@ -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<QtHighlighter>(document(), language);
m_highlighter = std::make_shared<QtHighlighter>(document(), locationFile->getLanguage());
m_highlighter->highlightDocument();
ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
+2 -2
View File
@@ -19,8 +19,8 @@ QtCodeSnippet* QtCodeSnippet::merged(
SourceLocationFile* aFile = a->m_codeArea->getSourceLocationFile().get();
SourceLocationFile* bFile = b->m_codeArea->getSourceLocationFile().get();
std::shared_ptr<SourceLocationFile> locationFile =
std::make_shared<SourceLocationFile>(aFile->getFilePath(), aFile->isWhole(), aFile->isComplete(), aFile->isIndexed());
std::shared_ptr<SourceLocationFile> locationFile = std::make_shared<SourceLocationFile>(
aFile->getFilePath(), aFile->getLanguage(), aFile->isWhole(), aFile->isComplete(), aFile->isIndexed());
aFile->forEachSourceLocation(
[&locationFile](SourceLocation* loc)
+5
View File
@@ -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();
+209 -125
View File
@@ -1,112 +1,141 @@
#include "QtHighlighter.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QTextBlock>
#include <QTextCursor>
#include <QTextDocument>
#include "ColorScheme.h"
#include "FileSystem.h"
#include "ResourcePaths.h"
#include "TextAccess.h"
#include "tracing.h"
#include "utility.h"
QVector<QtHighlighter::HighlightingRule> QtHighlighter::s_highlightingRules;
QVector<QtHighlighter::HighlightingRule> QtHighlighter::s_highlightingRulesCpp;
QVector<QtHighlighter::HighlightingRule> QtHighlighter::s_highlightingRulesJava;
QtHighlighter::HighlightingRule QtHighlighter::s_stringQuotationRule;
QtHighlighter::HighlightingRule QtHighlighter::s_charQuotationRule;
QtHighlighter::HighlightingRule QtHighlighter::s_commentRule;
std::map<std::wstring, std::vector<QtHighlighter::HighlightingRule>> 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<HighlightType, 8> 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<HighlightType, QColor> ruleTypeColors;
const std::array<HighlightType, 8> 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 = 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<HighlightingRule> 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<HighlightingRule> 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<HighlightingRule>& 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<std::pair<int, int>> QtHighlighter::createMultiLineCommentRanges(
QTextDocument* doc, std::vector<std::pair<int, int>>* 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<std::pair<int, int>> multiLineCommentRanges;
if (!multiLineCommentStartRule || !multiLineCommentEndRule)
{
return multiLineCommentRanges;
}
QTextCursor cursorStart(doc);
QTextCursor cursorEnd(doc);
std::vector<std::pair<int, int>> 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<std::pair<int, int>> 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<std::pair<int, int>>& ranges) const
+24 -15
View File
@@ -3,18 +3,31 @@
#include <QTextCharFormat>
#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<HighlightingRule>& quotationRules);
std::vector<std::pair<int, int>> createMultiLineCommentRanges(
QTextDocument* doc, std::vector<std::pair<int, int>>* ranges);
@@ -50,19 +66,12 @@ private:
QTextDocument* document() const;
static QVector<HighlightingRule> s_highlightingRules;
static QVector<HighlightingRule> s_highlightingRulesCpp;
static QVector<HighlightingRule> s_highlightingRulesJava;
static HighlightingRule s_stringQuotationRule;
static HighlightingRule s_charQuotationRule;
static HighlightingRule s_commentRule;
static std::map<std::wstring, std::vector<HighlightingRule>> s_highlightingRules;
static QTextCharFormat s_textFormat;
QTextDocument* m_document;
LanguageType m_language;
QVector<HighlightingRule> m_highlightingRules;
std::vector<HighlightingRule> m_highlightingRules;
std::vector<std::pair<int, int>> m_quotationRanges;
std::vector<std::pair<int, int>> m_multiLineCommentRanges;
std::vector<bool> m_highlightedLines;