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:
@@ -143,7 +143,7 @@
|
||||
</line_number>
|
||||
|
||||
<syntax>
|
||||
<normal>#D4D4D4</normal>
|
||||
<text>#D4D4D4</text>
|
||||
<directive>#00A0B6</directive>
|
||||
<keyword>#00BCD6</keyword>
|
||||
<type>#FF5961</type>
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
</line_number>
|
||||
|
||||
<syntax>
|
||||
<normal>black</normal>
|
||||
<text>black</text>
|
||||
<directive>#1B8856</directive>
|
||||
<keyword>#1B8856</keyword>
|
||||
<type>#C1492D</type>
|
||||
|
||||
@@ -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]*" ]
|
||||
}
|
||||
]
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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")
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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/");
|
||||
|
||||
@@ -9,6 +9,7 @@ class ResourcePaths
|
||||
{
|
||||
public:
|
||||
static FilePath getColorSchemesPath();
|
||||
static FilePath getSyntaxHighlightingRulesPath();
|
||||
static FilePath getFallbackPath();
|
||||
static FilePath getFontsPath();
|
||||
static FilePath getGuiPath();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user