4103 lines
167 KiB
C++
4103 lines
167 KiB
C++
/*******************************************
|
|
* Zira Editor
|
|
* A lightweight PHP Editor
|
|
* (C)2019 https://github.com/ziracms/editor
|
|
*******************************************/
|
|
|
|
#include "highlight.h"
|
|
#include <QTextDocument>
|
|
#include <QTextStream>
|
|
#include <QTextCursor>
|
|
#include <QTextBlock>
|
|
#include "helper.h"
|
|
|
|
const std::string MODE_PHP = "php";
|
|
const std::string MODE_JS = "js";
|
|
const std::string MODE_CSS = "css";
|
|
const std::string MODE_HTML = "html";
|
|
const std::string MODE_MIXED = "mixed";
|
|
const std::string MODE_UNKNOWN = "unknown";
|
|
|
|
const int STATE_NONE = 0;
|
|
const int STATE_COMMENT_ML_CSS = 1;
|
|
const int STATE_COMMENT_ML_JS = 2;
|
|
const int STATE_COMMENT_SL_JS = 3;
|
|
const int STATE_COMMENT_ML_PHP = 4;
|
|
const int STATE_COMMENT_SL_PHP = 5;
|
|
const int STATE_COMMENT_ML_HTML = 6;
|
|
const int STATE_STRING_SQ_HTML = 7;
|
|
const int STATE_STRING_DQ_HTML = 8;
|
|
const int STATE_STRING_SQ_JS = 9;
|
|
const int STATE_STRING_DQ_JS = 10;
|
|
const int STATE_STRING_SQ_PHP = 11;
|
|
const int STATE_STRING_DQ_PHP = 12;
|
|
const int STATE_STRING_HEREDOC = 13;
|
|
const int STATE_STRING_NOWDOC = 14;
|
|
const int STATE_STRING_SQ_CSS = 15;
|
|
const int STATE_STRING_DQ_CSS = 16;
|
|
const int STATE_TAG = 17;
|
|
const int STATE_REGEXP_JS = 18;
|
|
const int STATE_EXPRESSION_JS = 19;
|
|
const int STATE_EXPRESSION_PHP = 20;
|
|
const int STATE_COMMENT_SL_UNKNOWN = 21;
|
|
const int STATE_COMMENT_ML_UNKNOWN = 22;
|
|
const int STATE_STRING_SQ_UNKNOWN = 23;
|
|
const int STATE_STRING_DQ_UNKNOWN = 24;
|
|
|
|
const QString EXTENSION_DART = "dart";
|
|
const QString EXTENSION_INI = "ini";
|
|
const QString EXTENSION_TXT = "txt";
|
|
const QString EXTENSION_MD = "md";
|
|
|
|
const QString CMAKE_LISTS_FILENAME = "CMakeLists";
|
|
const QString ROBOTS_FILENAME = "robots";
|
|
|
|
const int EXTRA_HIGHLIGHT_BLOCKS_COUNT = 100; // should be >= 1
|
|
|
|
Highlight::Highlight(QTextDocument * parent) :
|
|
doc(parent)
|
|
{
|
|
std::string highlightTabsStr = Settings::get("highlight_tabs");
|
|
std::string highlightSpacesStr = Settings::get("highlight_spaces");
|
|
if (highlightTabsStr == "yes") highlightTabs = true;
|
|
else highlightTabs = false;
|
|
if (highlightSpacesStr == "yes") highlightSpaces = true;
|
|
else highlightSpaces = false;
|
|
|
|
// highlight modes by extension
|
|
QString phpExtentionsStr = QString::fromStdString(Settings::get("highlight_php_extensions"));
|
|
QStringList phpExtensionsList = phpExtentionsStr.split(",");
|
|
for (int i=0; i<phpExtensionsList.size(); i++) {
|
|
QString ext = phpExtensionsList.at(i);
|
|
modeTypes[ext.trimmed().toStdString()] = MODE_MIXED;
|
|
}
|
|
QString jsExtentionsStr = QString::fromStdString(Settings::get("highlight_js_extensions"));
|
|
QStringList jsExtensionsList = jsExtentionsStr.split(",");
|
|
for (int i=0; i<jsExtensionsList.size(); i++) {
|
|
QString ext = jsExtensionsList.at(i);
|
|
modeTypes[ext.trimmed().toStdString()] = MODE_JS;
|
|
}
|
|
QString cssExtentionsStr = QString::fromStdString(Settings::get("highlight_css_extensions"));
|
|
QStringList cssExtensionsList = cssExtentionsStr.split(",");
|
|
for (int i=0; i<cssExtensionsList.size(); i++) {
|
|
QString ext = cssExtensionsList.at(i);
|
|
modeTypes[ext.trimmed().toStdString()] = MODE_CSS;
|
|
}
|
|
QString htmlExtentionsStr = QString::fromStdString(Settings::get("highlight_html_extensions"));
|
|
QStringList htmlExtensionsList = htmlExtentionsStr.split(",");
|
|
for (int i=0; i<htmlExtensionsList.size(); i++) {
|
|
QString ext = htmlExtensionsList.at(i);
|
|
modeTypes[ext.trimmed().toStdString()] = MODE_HTML;
|
|
}
|
|
|
|
std::string spellColorStr = Settings::get("editor_line_warning_color");
|
|
spellColor = QColor(QString::fromStdString(spellColorStr));
|
|
|
|
std::string errorColorStr = Settings::get("editor_line_error_color");
|
|
errorColor = QColor(QString::fromStdString(errorColorStr));
|
|
|
|
enabled = false;
|
|
modeType = MODE_UNKNOWN;
|
|
block_state = 0;
|
|
highlightVarsMode = false;
|
|
firstRunMode = false;
|
|
rehighlightBlockMode = false;
|
|
lastVisibleBlockNumber = -1;
|
|
dirty = false;
|
|
isBigFile = false;
|
|
extension = "";
|
|
jsExtMode = "";
|
|
fileName = "";
|
|
|
|
HW = &HighlightWords::instance();
|
|
}
|
|
|
|
void Highlight::setFormat(int start, int count, const QTextCharFormat &format)
|
|
{
|
|
if (start < 0 || start >= formatChanges.count()) return;
|
|
const int end = qMin(start + count, formatChanges.count());
|
|
for (int i = start; i < end; i++) {
|
|
formatChanges[i] = format;
|
|
}
|
|
}
|
|
|
|
QTextCharFormat Highlight::format(int pos) const
|
|
{
|
|
if (pos < 0 || pos >= formatChanges.count()) return QTextCharFormat();
|
|
return formatChanges.at(pos);
|
|
}
|
|
|
|
void Highlight::applyFormatChanges(bool markDirty)
|
|
{
|
|
QTextLayout *layout = cBlock.layout();
|
|
QVector<QTextLayout::FormatRange> ranges;
|
|
int i = 0;
|
|
while (i < formatChanges.count()) {
|
|
QTextLayout::FormatRange r;
|
|
while (i < formatChanges.count() && formatChanges.at(i) == r.format) ++i;
|
|
if (i == formatChanges.count()) break;
|
|
r.start = i;
|
|
r.format = formatChanges.at(i);
|
|
while (i < formatChanges.count() && formatChanges.at(i) == r.format) ++i;
|
|
Q_ASSERT(i <= formatChanges.count());
|
|
r.length = i - r.start;
|
|
ranges << r;
|
|
}
|
|
layout->setFormats(ranges);
|
|
if (markDirty) doc->markContentsDirty(cBlock.position(), cBlock.length() > 0 ? 1 : 0);
|
|
}
|
|
|
|
std::string Highlight::getModeType()
|
|
{
|
|
return modeType;
|
|
}
|
|
|
|
std::string Highlight::getMode()
|
|
{
|
|
return mode;
|
|
}
|
|
|
|
void Highlight::reset()
|
|
{
|
|
state = STATE_NONE;
|
|
prevState = STATE_NONE;
|
|
prevPrevState = STATE_NONE;
|
|
mode = MODE_HTML;
|
|
prevMode = mode;
|
|
modeStarts.clear();
|
|
modeEnds.clear();
|
|
modeTags.clear();
|
|
stateStarts.clear();
|
|
stateEnds.clear();
|
|
stateIds.clear();
|
|
stringBlock = "";
|
|
stringBstring = "";
|
|
modeString = "";
|
|
modeStringC = "";
|
|
modeExpect = "";
|
|
modeExpectC = "";
|
|
modeSkip = false;
|
|
modeSkipC = false;
|
|
modeSpos = -1;
|
|
modeCpos = -1;
|
|
modeCposed = -1;
|
|
prevModeString = "";
|
|
prevModeStringC = "";
|
|
prevModeExpect = "";
|
|
prevModeExpectC = "";
|
|
prevModeSkip = false;
|
|
prevModeSkipC = false;
|
|
prevModeSpos = -1;
|
|
prevModeCpos = -1;
|
|
tagOpened = -1;
|
|
commentHTMLString = "";
|
|
commentHTMLOpened = -1;
|
|
stringSQOpenedHTML = -1;
|
|
stringDQOpenedHTML = -1;
|
|
stringSQOpenedCSS = -1;
|
|
stringDQOpenedCSS = -1;
|
|
stringSQOpenedJS = -1;
|
|
stringDQOpenedJS = -1;
|
|
stringSQOpenedPHP = -1;
|
|
stringDQOpenedPHP = -1;
|
|
stringBOpened = -1;
|
|
stringBStart = -1;
|
|
commentSLOpenedJS = -1;
|
|
commentMLOpenedJS = -1;
|
|
commentSLOpenedPHP = -1;
|
|
commentMLOpenedPHP = -1;
|
|
commentMLOpenedCSS = -1;
|
|
commentSLOpenedUnknown = -1;
|
|
stringSQOpenedUnknown = -1;
|
|
stringDQOpenedUnknown = -1;
|
|
commentMLOpenedUnknown = -1;
|
|
commentJSStringML = "";
|
|
commentPHPStringML = "";
|
|
commentJSStringSL = "";
|
|
commentPHPStringSL = "";
|
|
commentCSSStringML = "";
|
|
commentUnknownStringSL = "";
|
|
commentUnknownStringML = "";
|
|
stringEscStringCSS = "";
|
|
stringEscStringJS = "";
|
|
prevStringEscStringCSS = "";
|
|
prevStringEscStringJS = "";
|
|
stringEscStringPHP = "";
|
|
stringEscStringUnknown = "";
|
|
stringBExpect = -1;
|
|
regexpOpenedJS = -1;
|
|
regexpEscStringJS = "";
|
|
prevRegexpEscStringJS = "";
|
|
regexpPrevCharJS = "";
|
|
keywordStringJS = "";
|
|
keywordStringCSS = "";
|
|
keywordStringPHP = "";
|
|
keywordStringHTML = "";
|
|
keywordStringUnknown = "";
|
|
keywordJSOpened = -1;
|
|
keywordCSSOpened = -1;
|
|
keywordPHPOpened = -1;
|
|
keywordHTMLOpened = -1;
|
|
keywordUnknownOpened = -1;
|
|
exprOpenedPHP = -1;
|
|
exprOpenedJS = -1;
|
|
exprEscStringPHP = "";
|
|
exprEscStringJS = "";
|
|
prevExprEscStringJS = "";
|
|
keywordJSprevChar = "";
|
|
keywordCSSprevChar = "";
|
|
keywordCSSprevPrevChar = "";
|
|
keywordPHPprevChar = "";
|
|
keywordPHPprevPrevChar = "";
|
|
keywordPHPprevString = "";
|
|
keywordPHPprevStringPrevChar = "";
|
|
keywordJSprevString = "";
|
|
keywordJSprevStringPrevChar = "";
|
|
stringEscVariablePHP = "";
|
|
stringEscVariableJS = "";
|
|
prevStringEscVariableJS = "";
|
|
keywordHTMLprevChar = "";
|
|
keywordHTMLprevPrevChar = "";
|
|
keywordUnknownprevChar = "";
|
|
bracesCSS = 0;
|
|
bracesJS = 0;
|
|
bracesPHP = 0;
|
|
parensCSS = 0;
|
|
parensJS = 0;
|
|
parensPHP = 0;
|
|
cssMediaScope = false;
|
|
keywordPHPScopedOpened = -1;
|
|
keywordPHPScoped = false;
|
|
keywordJSScopedOpened = -1;
|
|
keywordJSScoped = false;
|
|
specialChars.clear();
|
|
specialCharsPos.clear();
|
|
specialWords.clear();
|
|
specialWordsPos.clear();
|
|
nsNamePHP = "";
|
|
nsChainPHP = "";
|
|
nsScopeChainPHP.clear();
|
|
nsStartsPHP.clear();
|
|
nsEndsPHP.clear();
|
|
nsNamesPHP.clear();
|
|
clsNamePHP = "";
|
|
clsScopeChainPHP.clear();
|
|
clsChainPHP = "";
|
|
clsStartsPHP.clear();
|
|
clsEndsPHP.clear();
|
|
clsNamesPHP.clear();
|
|
funcNamePHP = "";
|
|
funcScopeChainPHP.clear();
|
|
funcChainPHP = "";
|
|
funcStartsPHP.clear();
|
|
funcEndsPHP.clear();
|
|
funcNamesPHP.clear();
|
|
expectedNsNamePHP = "";
|
|
expectedClsNamePHP = "";
|
|
expectedFuncNamePHP = "";
|
|
expectedFuncParsPHP = -1;
|
|
expectedFuncArgsPHP.clear();
|
|
expectedFuncArgsPHPPositions.clear();
|
|
expectedFuncArgsPHPBlocks.clear();
|
|
nsScopePHP = -1;
|
|
clsScopePHP = -1;
|
|
funcScopePHP = -1;
|
|
varsChainsPHP.clear();
|
|
usedVarsChainsPHP.clear();
|
|
varsGlobChainPHP = "";
|
|
usedVarsGlobChainPHP = "";
|
|
varsClsChainPHP = "";
|
|
varsChainPHP = "";
|
|
usedVarsChainPHP = "";
|
|
clsOpenPHP = false;
|
|
clsOpensPHP.clear();
|
|
varsClsOpenChainPHP = "";
|
|
clsPropsChainPHP.clear();
|
|
isGlobalPHP = false;
|
|
funcNameJS = "";
|
|
funcScopeChainJS.clear();
|
|
funcChainJS = "";
|
|
funcStartsJS.clear();
|
|
funcEndsJS.clear();
|
|
funcNamesJS.clear();
|
|
expectedFuncNameJS = "";
|
|
expectedFuncVarJS = "";
|
|
expectedFuncParsJS = -1;
|
|
funcScopeJS = -1;
|
|
varsChainJS = "";
|
|
expectedFuncArgsJS.clear();
|
|
mediaNameCSS = "";
|
|
mediaStartsCSS.clear();
|
|
mediaEndsCSS.clear();
|
|
mediaNamesCSS.clear();
|
|
expectedMediaNameCSS = "";
|
|
cssNamesChain = "";
|
|
expectedMediaParsCSS = -1;
|
|
mediaScopeCSS = -1;
|
|
isColorKeyword = true;
|
|
tagChainHTML = "";
|
|
tagChainStartsHTML.clear();
|
|
tagChainEndsHTML.clear();
|
|
tagChainsHTML.clear();
|
|
variables.clear();
|
|
usedVariables.clear();
|
|
clsProps.clear();
|
|
jsNames.clear();
|
|
cssNames.clear();
|
|
expectAndSignPHP = false;
|
|
expectOrSignPHP = false;
|
|
operatorsChainPHP = "";
|
|
operatorsPHP.clear();
|
|
expectAndSignJS = false;
|
|
expectOrSignJS = false;
|
|
operatorsChainJS = "";
|
|
operatorsJS.clear();
|
|
expectJSVar = false;
|
|
expectVarInit = false;
|
|
prevIsKeyword = false;
|
|
expectedClsNameJS = "";
|
|
clsNameJS = "";
|
|
clsScopeJS = -1;
|
|
clsChainJS = "";
|
|
clsNamesJS.clear();
|
|
clsStartsJS.clear();
|
|
clsEndsJS.clear();
|
|
clsScopeChainJS.clear();
|
|
clsOpensJS.clear();
|
|
clsOpenJS = false;
|
|
}
|
|
|
|
void Highlight::addSpecialChar(QChar c, int pos)
|
|
{
|
|
specialChars.append(c);
|
|
specialCharsPos.append(pos);
|
|
}
|
|
|
|
void Highlight::addSpecialWord(QString w, int pos)
|
|
{
|
|
specialWords.append(w);
|
|
specialWordsPos.append(pos);
|
|
}
|
|
|
|
void Highlight::resetMode()
|
|
{
|
|
enabled = false;
|
|
modeType = MODE_UNKNOWN;
|
|
block_state = 0;
|
|
highlightVarsMode = false;
|
|
firstRunMode = false;
|
|
rehighlightBlockMode = false;
|
|
lastVisibleBlockNumber = -1;
|
|
dirty = false;
|
|
foundModes.clear();
|
|
extension = "";
|
|
jsExtMode = "";
|
|
fileName = "";
|
|
}
|
|
|
|
void Highlight::setIsBigFile(bool isBig)
|
|
{
|
|
isBigFile = isBig;
|
|
}
|
|
|
|
QString Highlight::getJsExtMode()
|
|
{
|
|
return jsExtMode;
|
|
}
|
|
|
|
void Highlight::setFileName(QString name)
|
|
{
|
|
fileName = name;
|
|
}
|
|
|
|
bool Highlight::isTextMode()
|
|
{
|
|
if (modeType != MODE_UNKNOWN) return false;
|
|
return extension.size() == 0 || (extension == EXTENSION_TXT && fileName != ROBOTS_FILENAME && fileName != CMAKE_LISTS_FILENAME) || extension == EXTENSION_MD;
|
|
}
|
|
|
|
void Highlight::initMode(QString ext, int lastBlockNumber)
|
|
{
|
|
enabled = true;
|
|
if (ext.size()==0) return;
|
|
extension = ext;
|
|
jsExtMode = "";
|
|
modeTypesIterator = modeTypes.find(ext.toLower().toStdString());
|
|
if (modeTypesIterator != modeTypes.end()) {
|
|
modeType = modeTypesIterator->second;
|
|
lastVisibleBlockNumber = lastBlockNumber;
|
|
if (modeType != MODE_MIXED) {
|
|
foundModes.append(QString::fromStdString(modeType));
|
|
}
|
|
if (modeType == MODE_JS && extension == EXTENSION_DART) {
|
|
jsExtMode = EXTENSION_DART;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Highlight::updateBlocks(int lastBlockNumber)
|
|
{
|
|
if (!enabled) return;
|
|
lastVisibleBlockNumber = lastBlockNumber;
|
|
QTextCursor curs = QTextCursor(doc);
|
|
curs.movePosition(QTextCursor::Start);
|
|
bool wantUpdate = false;
|
|
do {
|
|
QTextBlock block = curs.block();
|
|
if (!block.isValid()) break;
|
|
if (block.blockNumber() > lastVisibleBlockNumber + EXTRA_HIGHLIGHT_BLOCKS_COUNT) break;
|
|
HighlightData * userData = dynamic_cast<HighlightData *>(block.userData());
|
|
if (userData != nullptr && userData->wantUpdate) {
|
|
wantUpdate = true;
|
|
break;
|
|
}
|
|
} while(curs.movePosition(QTextCursor::NextBlock));
|
|
if (wantUpdate) highlightChanges(curs);
|
|
}
|
|
|
|
std::string Highlight::findModeAtCursor(QTextBlock * block, int pos)
|
|
{
|
|
if (modeType != MODE_MIXED) return modeType;
|
|
HighlightData * blockData = dynamic_cast<HighlightData *>(block->userData());
|
|
if (blockData != nullptr && blockData->modeStarts.size()>0 && blockData->modeEnds.size()>0 && blockData->modeTags.size()>0 &&
|
|
blockData->modeStarts.size()==blockData->modeEnds.size() && blockData->modeStarts.size()==blockData->modeTags.size()
|
|
) {
|
|
for (int i=0; i<blockData->modeStarts.size(); i++) {
|
|
if (blockData->modeStarts.at(i) <= pos && blockData->modeEnds.at(i) >= pos) {
|
|
return blockData->modeTags.at(i);
|
|
}
|
|
}
|
|
}
|
|
return MODE_HTML;
|
|
}
|
|
|
|
int Highlight::findStateAtCursor(QTextBlock * block, int pos)
|
|
{
|
|
HighlightData * blockData = dynamic_cast<HighlightData *>(block->userData());
|
|
if (blockData != nullptr && blockData->stateStarts.size()>0 && blockData->stateEnds.size()>0 && blockData->stateIds.size()>0 &&
|
|
blockData->stateStarts.size()==blockData->stateEnds.size() && blockData->stateStarts.size()==blockData->stateIds.size()
|
|
) {
|
|
for (int i=0; i<blockData->stateStarts.size(); i++) {
|
|
if (blockData->stateStarts.at(i) <= pos && blockData->stateEnds.at(i) >= pos) {
|
|
return blockData->stateIds.at(i);
|
|
}
|
|
}
|
|
}
|
|
return STATE_NONE;
|
|
}
|
|
|
|
bool Highlight::isStateOpen(QTextBlock * block, int pos)
|
|
{
|
|
int openState = findStateAtCursor(block, pos);
|
|
return (openState != STATE_NONE && openState != STATE_TAG) ? true : false;
|
|
}
|
|
|
|
QString Highlight::findNsPHPAtCursor(QTextBlock * block, int pos)
|
|
{
|
|
HighlightData * blockData = dynamic_cast<HighlightData *>(block->userData());
|
|
if (blockData != nullptr && blockData->nsStartsPHP.size()>0 && blockData->nsEndsPHP.size()>0 && blockData->nsNamesPHP.size()>0 &&
|
|
blockData->nsStartsPHP.size()==blockData->nsEndsPHP.size() && blockData->nsStartsPHP.size()==blockData->nsNamesPHP.size()
|
|
) {
|
|
for (int i=0; i<blockData->nsStartsPHP.size(); i++) {
|
|
if (blockData->nsStartsPHP.at(i) <= pos && blockData->nsEndsPHP.at(i) >= pos) {
|
|
return blockData->nsNamesPHP.at(i);
|
|
}
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
QString Highlight::findClsPHPAtCursor(QTextBlock * block, int pos)
|
|
{
|
|
HighlightData * blockData = dynamic_cast<HighlightData *>(block->userData());
|
|
if (blockData != nullptr && blockData->clsStartsPHP.size()>0 && blockData->clsEndsPHP.size()>0 && blockData->clsNamesPHP.size()>0 &&
|
|
blockData->clsStartsPHP.size()==blockData->clsEndsPHP.size() && blockData->clsStartsPHP.size()==blockData->clsNamesPHP.size()
|
|
) {
|
|
for (int i=0; i<blockData->clsStartsPHP.size(); i++) {
|
|
if (blockData->clsStartsPHP.at(i) <= pos && blockData->clsEndsPHP.at(i) >= pos) {
|
|
return blockData->clsNamesPHP.at(i);
|
|
}
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
QString Highlight::findFuncPHPAtCursor(QTextBlock * block, int pos)
|
|
{
|
|
HighlightData * blockData = dynamic_cast<HighlightData *>(block->userData());
|
|
if (blockData != nullptr && blockData->funcStartsPHP.size()>0 && blockData->funcEndsPHP.size()>0 && blockData->funcNamesPHP.size()>0 &&
|
|
blockData->funcStartsPHP.size()==blockData->funcEndsPHP.size() && blockData->funcStartsPHP.size()==blockData->funcNamesPHP.size()
|
|
) {
|
|
for (int i=0; i<blockData->funcStartsPHP.size(); i++) {
|
|
if (blockData->funcStartsPHP.at(i) <= pos && blockData->funcEndsPHP.at(i) >= pos) {
|
|
return blockData->funcNamesPHP.at(i);
|
|
}
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
QString Highlight::findClsJSAtCursor(QTextBlock * block, int pos)
|
|
{
|
|
HighlightData * blockData = dynamic_cast<HighlightData *>(block->userData());
|
|
if (blockData != nullptr && blockData->clsStartsJS.size()>0 && blockData->clsEndsJS.size()>0 && blockData->clsNamesJS.size()>0 &&
|
|
blockData->clsStartsJS.size()==blockData->clsEndsJS.size() && blockData->clsStartsJS.size()==blockData->clsNamesJS.size()
|
|
) {
|
|
for (int i=0; i<blockData->clsStartsJS.size(); i++) {
|
|
if (blockData->clsStartsJS.at(i) <= pos && blockData->clsEndsJS.at(i) >= pos) {
|
|
return blockData->clsNamesJS.at(i);
|
|
}
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
QString Highlight::findFuncJSAtCursor(QTextBlock * block, int pos)
|
|
{
|
|
HighlightData * blockData = dynamic_cast<HighlightData *>(block->userData());
|
|
if (blockData != nullptr && blockData->funcStartsJS.size()>0 && blockData->funcEndsJS.size()>0 && blockData->funcNamesJS.size()>0 &&
|
|
blockData->funcStartsJS.size()==blockData->funcEndsJS.size() && blockData->funcStartsJS.size()==blockData->funcNamesJS.size()
|
|
) {
|
|
for (int i=0; i<blockData->funcStartsJS.size(); i++) {
|
|
if (blockData->funcStartsJS.at(i) <= pos && blockData->funcEndsJS.at(i) >= pos) {
|
|
return blockData->funcNamesJS.at(i);
|
|
}
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
QString Highlight::findMediaCSSAtCursor(QTextBlock * block, int pos)
|
|
{
|
|
HighlightData * blockData = dynamic_cast<HighlightData *>(block->userData());
|
|
if (blockData != nullptr && blockData->mediaStartsCSS.size()>0 && blockData->mediaEndsCSS.size()>0 && blockData->mediaNamesCSS.size()>0 &&
|
|
blockData->mediaStartsCSS.size()==blockData->mediaEndsCSS.size() && blockData->mediaStartsCSS.size()==blockData->mediaNamesCSS.size()
|
|
) {
|
|
for (int i=0; i<blockData->mediaStartsCSS.size(); i++) {
|
|
if (blockData->mediaStartsCSS.at(i) <= pos && blockData->mediaEndsCSS.at(i) >= pos) {
|
|
return blockData->mediaNamesCSS.at(i);
|
|
}
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
QString Highlight::findTagChainHTMLAtCursor(QTextBlock * block, int pos)
|
|
{
|
|
HighlightData * blockData = dynamic_cast<HighlightData *>(block->userData());
|
|
if (blockData != nullptr && blockData->tagChainStartsHTML.size()>0 && blockData->tagChainEndsHTML.size()>0 && blockData->tagChainsHTML.size()>0 &&
|
|
blockData->tagChainStartsHTML.size()==blockData->tagChainEndsHTML.size() && blockData->tagChainStartsHTML.size()==blockData->tagChainsHTML.size()
|
|
) {
|
|
for (int i=0; i<blockData->tagChainStartsHTML.size(); i++) {
|
|
if (blockData->tagChainStartsHTML.at(i) <= pos && blockData->tagChainEndsHTML.at(i) >= pos) {
|
|
return blockData->tagChainsHTML.at(i);
|
|
}
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
QStringList Highlight::getKnownVars(QString clsName, QString funcName)
|
|
{
|
|
QStringList vars;
|
|
if (clsName == "anonymous class" || funcName == "anonymous function") return vars;
|
|
QString k = clsName + "::" + funcName;
|
|
knownVarsIterator = knownVars.find(k.toStdString());
|
|
if (knownVarsIterator != knownVars.end()) {
|
|
QString varsChain = QString::fromStdString(knownVarsIterator->second);
|
|
QStringList varsList = varsChain.split(",");
|
|
for (int i=0; i<varsList.size(); i++) {
|
|
QString varName = varsList.at(i);
|
|
varName = varName.trimmed();
|
|
if (varName.size() == 0) continue;
|
|
vars.append(varName);
|
|
}
|
|
}
|
|
return vars;
|
|
}
|
|
|
|
int Highlight::getKnownVarPosition(QString clsName, QString funcName, QString varName)
|
|
{
|
|
if (clsName == "anonymous class" || funcName == "anonymous function") return -1;
|
|
QString k = clsName + "::" + funcName;
|
|
knownVarsIterator = knownVars.find(k.toStdString());
|
|
if (knownVarsIterator != knownVars.end()) {
|
|
QString varsChain = QString::fromStdString(knownVarsIterator->second) + ",";
|
|
if (varsChain.indexOf(varName + ",") < 0) return - 1;
|
|
}
|
|
QString kk = k + "::" + varName;
|
|
knownVarsPositionsIterator = knownVarsPositions.find(kk.toStdString());
|
|
if (knownVarsPositionsIterator != knownVarsPositions.end()) {
|
|
return knownVarsPositionsIterator->second;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int Highlight::getKnownVarBlockNumber(QString clsName, QString funcName, QString varName)
|
|
{
|
|
if (clsName == "anonymous class" || funcName == "anonymous function") return -1;
|
|
QString k = clsName + "::" + funcName;
|
|
knownVarsIterator = knownVars.find(k.toStdString());
|
|
if (knownVarsIterator != knownVars.end()) {
|
|
QString varsChain = QString::fromStdString(knownVarsIterator->second) + ",";
|
|
if (varsChain.indexOf(varName + ",") < 0) return - 1;
|
|
}
|
|
QString kk = k + "::" + varName;
|
|
knownVarsBlocksIterator = knownVarsBlocks.find(kk.toStdString());
|
|
if (knownVarsBlocksIterator != knownVarsBlocks.end()) {
|
|
return knownVarsBlocksIterator->second;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
QStringList Highlight::getUsedVars(QString clsName, QString funcName)
|
|
{
|
|
QStringList vars;
|
|
if (clsName == "anonymous class" || funcName == "anonymous function") return vars;
|
|
QString k = clsName + "::" + funcName;
|
|
usedVarsIterator = usedVars.find(k.toStdString());
|
|
if (usedVarsIterator != usedVars.end()) {
|
|
QString varsChain = QString::fromStdString(usedVarsIterator->second);
|
|
QStringList varsList = varsChain.split(",");
|
|
for (int i=0; i<varsList.size(); i++) {
|
|
QString varName = varsList.at(i);
|
|
varName = varName.trimmed();
|
|
if (varName.size() == 0) continue;
|
|
vars.append(varName);
|
|
}
|
|
}
|
|
return vars;
|
|
}
|
|
|
|
QStringList Highlight::getKnownFunctions(QString clsName)
|
|
{
|
|
QStringList funcs;
|
|
if (clsName == "anonymous class") return funcs;
|
|
for (const auto &it : knownFunctions) {
|
|
QString k = QString::fromStdString(it.first);
|
|
if (clsName.size() > 0 && k.indexOf(clsName+"::") != 0) continue;
|
|
funcs.append(k);
|
|
}
|
|
return funcs;
|
|
}
|
|
|
|
void Highlight::setHighlightVarsMode(bool varsMode)
|
|
{
|
|
highlightVarsMode = varsMode;
|
|
}
|
|
|
|
void Highlight::setFirstRunMode(bool runMode)
|
|
{
|
|
firstRunMode = runMode;
|
|
}
|
|
|
|
QStringList Highlight::getFoundModes()
|
|
{
|
|
return foundModes;
|
|
}
|
|
|
|
void Highlight::highlightString(int start, int length, const QTextCharFormat format)
|
|
{
|
|
setFormat(start, length, format);
|
|
}
|
|
|
|
void Highlight::highlightChar(int start, const QTextCharFormat format)
|
|
{
|
|
setFormat(start, 1, format);
|
|
}
|
|
|
|
void Highlight::changeBlockState()
|
|
{
|
|
if (highlightVarsMode || firstRunMode) return;
|
|
cBlock.setUserState(static_cast<int>(++block_state));
|
|
}
|
|
|
|
bool Highlight::detectMode(const QChar & c, int pos, bool isWSpace, bool isLast)
|
|
{
|
|
bool changed;
|
|
if (mode == MODE_HTML) {
|
|
changed = detectModeOpen(c, pos, isWSpace, isLast);
|
|
} else {
|
|
changed = detectModeOpen(c, pos, isWSpace, isLast);
|
|
if (!changed) changed = detectModeClose(c, pos, isWSpace);
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
bool Highlight::detectModeOpen(const QChar & c, int pos, bool isWSpace, bool isLast)
|
|
{
|
|
std::string _mode = mode;
|
|
|
|
if (mode!=MODE_PHP && c.toLatin1() == '<') {
|
|
// php in opening tag
|
|
prevModeString = modeString;
|
|
prevModeExpect = modeExpect;
|
|
prevModeSkip = modeSkip;
|
|
prevModeSpos = modeSpos;
|
|
|
|
modeString = c;
|
|
modeExpect = "";
|
|
modeSkip = false;
|
|
modeSpos = pos;
|
|
return false;
|
|
}
|
|
|
|
if (modeString.size()==0) return false;
|
|
|
|
if (!isWSpace && !modeSkip) {
|
|
modeString += c;
|
|
}
|
|
|
|
if (modeString == "<?") {
|
|
modeExpect = MODE_PHP;
|
|
} else if (modeString == "<?php") {
|
|
modeExpect = MODE_PHP;
|
|
} else if (modeString == "<script") {
|
|
modeExpect = MODE_JS;
|
|
} else if (modeString == "<style") {
|
|
modeExpect = MODE_CSS;
|
|
} else {
|
|
modeExpect = "";
|
|
}
|
|
|
|
if (modeString == "<?=") {
|
|
mode = MODE_PHP;
|
|
} else if (modeExpect == MODE_PHP && (isWSpace || isLast)) {
|
|
mode = MODE_PHP;
|
|
} else if (_mode == MODE_HTML && modeString == "<script>") {
|
|
mode = MODE_JS;
|
|
} else if (_mode == MODE_HTML && modeExpect == MODE_JS && c.toLatin1() == '>') {
|
|
mode = MODE_JS;
|
|
} else if (_mode == MODE_HTML && modeString == "<style>") {
|
|
mode = MODE_CSS;
|
|
} else if (_mode == MODE_HTML && modeExpect == MODE_CSS && c.toLatin1() == '>') {
|
|
mode = MODE_CSS;
|
|
} else if (c.toLatin1() == '>' || modeString.size()>8) {
|
|
modeString = "";
|
|
modeExpect = "";
|
|
modeSpos = -1;
|
|
}
|
|
|
|
if (isWSpace) {
|
|
modeSkip = true;
|
|
}
|
|
|
|
if (mode != _mode) {
|
|
if (mode!=MODE_PHP && ((tagOpened>=0 && tagOpened!=modeSpos) || commentHTMLOpened>=0)) {
|
|
modeString = "";
|
|
modeExpect = "";
|
|
modeSkip = false;
|
|
modeCpos = -1;
|
|
|
|
mode = _mode;
|
|
return false;
|
|
} else if (mode!=MODE_PHP && (stringSQOpenedHTML>=0 || stringDQOpenedHTML>=0)) {
|
|
mode = _mode;
|
|
return false;
|
|
} else {
|
|
modeString = "";
|
|
modeExpect = "";
|
|
modeSkip = false;
|
|
modeCpos = -1;
|
|
|
|
prevMode = _mode;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectModeClose(const QChar & c, int pos, bool isWSpace)
|
|
{
|
|
std::string _mode = mode;
|
|
|
|
if (mode == MODE_PHP && stringSQOpenedPHP < 0 && stringDQOpenedPHP < 0 && stringBOpened < 0 && commentMLOpenedPHP < 0 && exprOpenedPHP < 0 && c.toLatin1() == '?') {
|
|
modeExpectC = "";
|
|
modeStringC = c;
|
|
modeCpos = pos;
|
|
modeCposed = modeCpos;
|
|
modeSkipC = false;
|
|
return false;
|
|
} else if (mode == MODE_JS && stringSQOpenedJS < 0 && stringDQOpenedJS < 0 && commentMLOpenedJS < 0 && regexpOpenedJS < 0 && exprOpenedJS < 0 && c.toLatin1() == '<') {
|
|
// php in closing tag
|
|
prevModeExpectC = modeExpectC;
|
|
prevModeStringC = modeStringC;
|
|
prevModeCpos = modeCpos;
|
|
prevModeSkipC = modeSkipC;
|
|
|
|
modeExpectC = "";
|
|
modeStringC = c;
|
|
modeCpos = pos;
|
|
modeCposed = modeCpos;
|
|
modeSkipC = false;
|
|
return false;
|
|
} else if (mode == MODE_CSS && commentMLOpenedCSS < 0 && c.toLatin1() == '<') {
|
|
// php in closing tag
|
|
prevModeExpectC = modeExpectC;
|
|
prevModeStringC = modeStringC;
|
|
prevModeCpos = modeCpos;
|
|
prevModeSkipC = modeSkipC;
|
|
|
|
modeExpectC = "";
|
|
modeStringC = c;
|
|
modeCpos = pos;
|
|
modeCposed = modeCpos;
|
|
modeSkipC = false;
|
|
return false;
|
|
}
|
|
|
|
if (modeStringC.size()==0) return false;
|
|
|
|
if (!isWSpace && !modeSkipC) {
|
|
modeStringC += c;
|
|
}
|
|
|
|
if (modeStringC == "</script") {
|
|
modeExpectC = MODE_JS;
|
|
} else if (modeStringC == "</style") {
|
|
modeExpectC = MODE_CSS;
|
|
} else {
|
|
modeExpectC = "";
|
|
}
|
|
|
|
if (mode == MODE_PHP && modeStringC == "?>") {
|
|
mode = prevMode;
|
|
} else if (mode == MODE_JS && modeStringC == "</script>") {
|
|
mode = prevMode;
|
|
} else if (mode == MODE_JS && modeExpectC == MODE_JS && c.toLatin1() == '>') {
|
|
mode = prevMode;
|
|
} else if (mode == MODE_CSS && modeStringC == "</style>") {
|
|
mode = prevMode;
|
|
} else if (mode == MODE_CSS && modeExpectC == MODE_CSS && c.toLatin1() == '>') {
|
|
mode = prevMode;
|
|
} else if (c.toLatin1() == '>' || modeStringC.size()>9) {
|
|
modeExpectC = "";
|
|
modeStringC = "";
|
|
modeCpos = -1;
|
|
}
|
|
|
|
if (isWSpace) {
|
|
modeSkipC = true;
|
|
}
|
|
|
|
if (mode != _mode) {
|
|
modeExpectC = "";
|
|
modeStringC = "";
|
|
modeSpos = -1;
|
|
modeSkipC = false;
|
|
prevMode = MODE_HTML;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectTag(const QChar & c, int pos)
|
|
{
|
|
if (stringSQOpenedHTML>=0 || stringDQOpenedHTML>=0) return false;
|
|
if (tagOpened < 0 && c.toLatin1() == '<') {
|
|
tagOpened = pos;
|
|
state = STATE_TAG;
|
|
return true;
|
|
} else if (tagOpened >= 0 && c.toLatin1() == '>' && commentHTMLOpened < 0) {
|
|
tagOpened = -1;
|
|
state = STATE_NONE;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectCommentHTML(const QChar & c)
|
|
{
|
|
if (tagOpened>=0 && commentHTMLOpened < 0 && commentHTMLString.size()<=4) {
|
|
commentHTMLString += c;
|
|
if (commentHTMLString=="<!--") {
|
|
commentHTMLString = "";
|
|
commentHTMLOpened = tagOpened;
|
|
state = STATE_COMMENT_ML_HTML;
|
|
return true;
|
|
}
|
|
} else if (tagOpened>=0 && commentHTMLOpened >= 0 && c.toLatin1() == '-' && commentHTMLString.size()<2) {
|
|
commentHTMLString += c;
|
|
} else if (tagOpened>=0 && commentHTMLOpened >= 0 && c.toLatin1() != '-' && c.toLatin1() != '>') {
|
|
commentHTMLString = "";
|
|
} else if (tagOpened>=0 && commentHTMLOpened >= 0 && c.toLatin1() == '>' && commentHTMLString == "--") {
|
|
commentHTMLString = "";
|
|
commentHTMLOpened = -1;
|
|
tagOpened = -1;
|
|
state = STATE_NONE;
|
|
return true;
|
|
} else if (tagOpened<0) {
|
|
commentHTMLString = "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectMLCommentCSS(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedCSS >= 0 || stringDQOpenedCSS >= 0 || commentMLOpenedCSS >= 0;
|
|
if (!opened && commentCSSStringML.size()==0 && c.toLatin1() == '/') {
|
|
commentCSSStringML = c;
|
|
} else if (!opened && commentCSSStringML.size()==1) {
|
|
commentCSSStringML += c;
|
|
if (commentCSSStringML=="/*") {
|
|
commentCSSStringML = "";
|
|
commentMLOpenedCSS = pos;
|
|
state = STATE_COMMENT_ML_CSS;
|
|
return true;
|
|
} else {
|
|
commentCSSStringML = "";
|
|
}
|
|
} else if (commentMLOpenedCSS >= 0 && c.toLatin1() == '*') {
|
|
commentCSSStringML = c;
|
|
} else if (commentMLOpenedCSS >= 0 && commentCSSStringML.size()==1) {
|
|
commentCSSStringML += c;
|
|
if (commentCSSStringML == "*/") {
|
|
commentCSSStringML = "";
|
|
commentMLOpenedCSS = -1;
|
|
state = STATE_NONE;
|
|
return true;
|
|
} else {
|
|
commentCSSStringML = "";
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectSLCommentJS(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedJS >= 0 || stringDQOpenedJS >= 0 || commentSLOpenedJS >= 0 || commentMLOpenedJS >= 0 || exprOpenedJS >= 0;
|
|
if (!opened && commentJSStringSL.size()==0 && c.toLatin1() == '/' && (regexpOpenedJS < 0 || regexpOpenedJS == pos)) {
|
|
commentJSStringSL = c;
|
|
} else if (!opened && commentJSStringSL.size()==1) {
|
|
commentJSStringSL += c;
|
|
if (commentJSStringSL=="//") {
|
|
commentJSStringSL = "";
|
|
commentSLOpenedJS = pos;
|
|
if (regexpOpenedJS>=0) {
|
|
regexpOpenedJS = -1;
|
|
}
|
|
state = STATE_COMMENT_SL_JS;
|
|
return true;
|
|
} else {
|
|
commentJSStringSL = "";
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectMLCommentJS(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedJS >= 0 || stringDQOpenedJS >= 0 || commentSLOpenedJS >= 0 || commentMLOpenedJS >= 0 || exprOpenedJS >= 0;
|
|
if (!opened && commentJSStringML.size()==0 && c.toLatin1() == '/' && (regexpOpenedJS < 0 || regexpOpenedJS == pos)) {
|
|
commentJSStringML = c;
|
|
} else if (!opened && commentJSStringML.size()==1) {
|
|
commentJSStringML += c;
|
|
if (commentJSStringML=="/*") {
|
|
commentJSStringML = "";
|
|
commentMLOpenedJS = pos;
|
|
if (regexpOpenedJS>=0) regexpOpenedJS = -1;
|
|
state = STATE_COMMENT_ML_JS;
|
|
return true;
|
|
} else {
|
|
commentJSStringML = "";
|
|
}
|
|
} else if (commentMLOpenedJS >= 0 && c.toLatin1() == '*') {
|
|
commentJSStringML = c;
|
|
} else if (commentMLOpenedJS >= 0 && commentJSStringML.size()==1) {
|
|
commentJSStringML += c;
|
|
if (commentJSStringML == "*/") {
|
|
commentJSStringML = "";
|
|
commentMLOpenedJS = -1;
|
|
state = STATE_NONE;
|
|
return true;
|
|
} else {
|
|
commentJSStringML = "";
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectMLCommentPHP(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedPHP >= 0 || stringDQOpenedPHP >= 0 || stringBOpened >= 0 || commentSLOpenedPHP >= 0 || commentMLOpenedPHP >= 0 || exprOpenedPHP >= 0;
|
|
if (!opened && commentPHPStringML.size()==0 && c.toLatin1() == '/') {
|
|
commentPHPStringML = c;
|
|
} else if (!opened && commentPHPStringML.size()==1) {
|
|
commentPHPStringML += c;
|
|
if (commentPHPStringML=="/*") {
|
|
commentPHPStringML = "";
|
|
commentMLOpenedPHP = pos;
|
|
state = STATE_COMMENT_ML_PHP;
|
|
return true;
|
|
} else {
|
|
commentPHPStringML = "";
|
|
}
|
|
} else if (commentMLOpenedPHP >= 0 && c.toLatin1() == '*') {
|
|
commentPHPStringML = c;
|
|
} else if (commentMLOpenedPHP >= 0 && commentPHPStringML.size()==1) {
|
|
commentPHPStringML += c;
|
|
if (commentPHPStringML == "*/") {
|
|
commentPHPStringML = "";
|
|
commentMLOpenedPHP = -1;
|
|
state = STATE_NONE;
|
|
return true;
|
|
} else {
|
|
commentPHPStringML = "";
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectSLCommentPHP(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedPHP >= 0 || stringDQOpenedPHP >= 0 || stringBOpened >= 0 || commentSLOpenedPHP >= 0 || commentMLOpenedPHP >= 0 || exprOpenedPHP >= 0;
|
|
if (!opened && commentPHPStringSL.size()==0 && (c.toLatin1() == '/' || c.toLatin1() == '#')) {
|
|
if (c.toLatin1() == '#') {
|
|
commentPHPStringSL = "";
|
|
commentSLOpenedPHP = pos;
|
|
state = STATE_COMMENT_SL_PHP;
|
|
return true;
|
|
} else {
|
|
commentPHPStringSL = c;
|
|
}
|
|
} else if (!opened && commentPHPStringSL.size()==1) {
|
|
commentPHPStringSL += c;
|
|
if (commentPHPStringSL=="//") {
|
|
commentPHPStringSL = "";
|
|
commentSLOpenedPHP = pos;
|
|
state = STATE_COMMENT_SL_PHP;
|
|
return true;
|
|
} else {
|
|
commentPHPStringSL = "";
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectStringSQHTML(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedHTML >= 0 || stringDQOpenedHTML >= 0 || commentHTMLOpened >= 0;
|
|
if (!opened && tagOpened >= 0 && c.toLatin1() == '\'') {
|
|
stringSQOpenedHTML = pos;
|
|
prevPrevState = prevState;
|
|
prevState = state;
|
|
state = STATE_STRING_SQ_HTML;
|
|
return true;
|
|
} else if (stringSQOpenedHTML >= 0 && c.toLatin1() == '\'') {
|
|
stringSQOpenedHTML = -1;
|
|
state = prevState;
|
|
prevState = prevPrevState;
|
|
prevPrevState = STATE_NONE;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectStringDQHTML(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedHTML >= 0 || stringDQOpenedHTML >= 0 || commentHTMLOpened >= 0;
|
|
if (!opened && tagOpened >= 0 && c.toLatin1() == '"') {
|
|
stringDQOpenedHTML = pos;
|
|
prevPrevState = prevState;
|
|
prevState = state;
|
|
state = STATE_STRING_DQ_HTML;
|
|
return true;
|
|
} else if (stringDQOpenedHTML >= 0 && c.toLatin1() == '"') {
|
|
stringDQOpenedHTML = -1;
|
|
state = prevState;
|
|
prevState = prevPrevState;
|
|
prevPrevState = STATE_NONE;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectStringSQCSS(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedCSS >= 0 || stringDQOpenedCSS >= 0 || commentMLOpenedCSS >= 0;
|
|
if (!opened && c.toLatin1() == '\'') {
|
|
stringSQOpenedCSS = pos;
|
|
prevPrevState = prevState;
|
|
prevState = state;
|
|
state = STATE_STRING_SQ_CSS;
|
|
stringEscStringCSS = "";
|
|
return true;
|
|
} else if (stringSQOpenedCSS >= 0 && c.toLatin1() == '\'' && stringEscStringCSS.size()%2 == 0) {
|
|
stringSQOpenedCSS = -1;
|
|
state = prevState;
|
|
prevState = prevPrevState;
|
|
prevPrevState = STATE_NONE;
|
|
stringEscStringCSS = "";
|
|
return true;
|
|
} else if (stringSQOpenedCSS >= 0 && c.toLatin1() == '\\') {
|
|
stringEscStringCSS += c;
|
|
} else if (stringSQOpenedCSS >= 0) {
|
|
if (c.toLatin1() == '<') prevStringEscStringCSS = stringEscStringCSS;
|
|
stringEscStringCSS = "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectStringDQCSS(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedCSS >= 0 || stringDQOpenedCSS >= 0 || commentMLOpenedCSS >= 0;
|
|
if (!opened && c.toLatin1() == '"') {
|
|
stringDQOpenedCSS = pos;
|
|
prevPrevState = prevState;
|
|
prevState = state;
|
|
state = STATE_STRING_DQ_CSS;
|
|
stringEscStringCSS = "";
|
|
return true;
|
|
} else if (stringDQOpenedCSS >= 0 && c.toLatin1() == '"' && stringEscStringCSS.size()%2 == 0) {
|
|
stringDQOpenedCSS = -1;
|
|
state = prevState;
|
|
prevState = prevPrevState;
|
|
prevPrevState = STATE_NONE;
|
|
stringEscStringCSS = "";
|
|
return true;
|
|
} else if (stringDQOpenedCSS >= 0 && c.toLatin1() == '\\') {
|
|
stringEscStringCSS += c;
|
|
} else if (stringDQOpenedCSS >= 0) {
|
|
if (c.toLatin1() == '<') prevStringEscStringCSS = stringEscStringCSS;
|
|
stringEscStringCSS = "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectStringSQJS(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedJS >= 0 || stringDQOpenedJS >= 0 || commentSLOpenedJS >= 0 || commentMLOpenedJS >= 0 || regexpOpenedJS >= 0 || exprOpenedJS >= 0;
|
|
if (!opened && c.toLatin1() == '\'') {
|
|
stringSQOpenedJS = pos;
|
|
prevPrevState = prevState;
|
|
prevState = state;
|
|
state = STATE_STRING_SQ_JS;
|
|
stringEscStringJS = "";
|
|
return true;
|
|
} else if (stringSQOpenedJS >= 0 && c.toLatin1() == '\'' && stringEscStringJS.size()%2 == 0) {
|
|
stringSQOpenedJS = -1;
|
|
state = prevState;
|
|
prevState = prevPrevState;
|
|
prevPrevState = STATE_NONE;
|
|
stringEscStringJS = "";
|
|
return true;
|
|
} else if (stringSQOpenedJS >= 0 && c.toLatin1() == '\\') {
|
|
stringEscStringJS += c;
|
|
} else if (stringSQOpenedJS >= 0) {
|
|
if (c.toLatin1() == '<') prevStringEscStringJS = stringEscStringJS;
|
|
stringEscStringJS = "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectStringDQJS(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedJS >= 0 || stringDQOpenedJS >= 0 || commentSLOpenedJS >= 0 || commentMLOpenedJS >= 0 || regexpOpenedJS >= 0 || exprOpenedJS >= 0;
|
|
if (!opened && c.toLatin1() == '"') {
|
|
stringDQOpenedJS = pos;
|
|
prevPrevState = prevState;
|
|
prevState = state;
|
|
state = STATE_STRING_DQ_JS;
|
|
stringEscStringJS = "";
|
|
return true;
|
|
} else if (stringDQOpenedJS >= 0 && c.toLatin1() == '"' && stringEscStringJS.size()%2 == 0) {
|
|
stringDQOpenedJS = -1;
|
|
state = prevState;
|
|
prevState = prevPrevState;
|
|
prevPrevState = STATE_NONE;
|
|
stringEscStringJS = "";
|
|
return true;
|
|
} else if (stringDQOpenedJS >= 0 && c.toLatin1() == '\\') {
|
|
stringEscStringJS += c;
|
|
} else if (stringDQOpenedJS >= 0) {
|
|
if (c.toLatin1() == '<') prevStringEscStringJS = stringEscStringJS;
|
|
stringEscStringJS = "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectStringSQPHP(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedPHP >= 0 || stringDQOpenedPHP >= 0 || stringBOpened >= 0 || commentSLOpenedPHP >= 0 || commentMLOpenedPHP >= 0 || exprOpenedPHP >= 0;
|
|
if (!opened && c.toLatin1() == '\'') {
|
|
stringSQOpenedPHP = pos;
|
|
state = STATE_STRING_SQ_PHP;
|
|
stringEscStringPHP = "";
|
|
return true;
|
|
} else if (stringSQOpenedPHP >= 0 && c.toLatin1() == '\'' && stringEscStringPHP.size()%2 == 0) {
|
|
stringSQOpenedPHP = -1;
|
|
state = STATE_NONE;
|
|
stringEscStringPHP = "";
|
|
return true;
|
|
} else if (stringSQOpenedPHP >= 0 && c.toLatin1() == '\\') {
|
|
stringEscStringPHP += c;
|
|
} else if (stringSQOpenedPHP >= 0) {
|
|
stringEscStringPHP = "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectStringDQPHP(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedPHP >= 0 || stringDQOpenedPHP >= 0 || stringBOpened >= 0 || commentSLOpenedPHP >= 0 || commentMLOpenedPHP >= 0 || exprOpenedPHP >= 0;
|
|
if (!opened && c.toLatin1() == '"') {
|
|
stringDQOpenedPHP = pos;
|
|
state = STATE_STRING_DQ_PHP;
|
|
stringEscStringPHP = "";
|
|
return true;
|
|
} else if (stringDQOpenedPHP >= 0 && c.toLatin1() == '"' && stringEscStringPHP.size()%2 == 0 && !keywordPHPScoped) {
|
|
stringDQOpenedPHP = -1;
|
|
state = STATE_NONE;
|
|
stringEscStringPHP = "";
|
|
return true;
|
|
} else if (stringDQOpenedPHP >= 0 && c.toLatin1() == '\\') {
|
|
stringEscStringPHP += c;
|
|
} else if (stringDQOpenedPHP >= 0) {
|
|
stringEscStringPHP = "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectStringBPHP(const QChar & c, int pos, bool isAlpha, bool isAlnum, bool isLast)
|
|
{
|
|
bool opened = stringBOpened >= 0 || commentSLOpenedPHP >= 0 || commentMLOpenedPHP >= 0 || exprOpenedPHP >= 0;
|
|
if (!opened && stringBstring.size()<=3 && c.toLatin1() == '<' && stringSQOpenedPHP < 0 && stringDQOpenedPHP < 0) {
|
|
stringBstring += c;
|
|
if (stringBStart<0) stringBStart = pos;
|
|
} else if (!opened && stringBstring.size()==3 && stringBlock.size()==0 && stringSQOpenedPHP < 0 && c.toLatin1() == '"' && stringBExpect < 0) {
|
|
stringDQOpenedPHP = -1;
|
|
state = STATE_NONE;
|
|
stringEscStringPHP = "";
|
|
stringBExpect = STATE_STRING_HEREDOC;
|
|
} else if (!opened && stringBstring.size()==3 && stringBlock.size()==0 && stringDQOpenedPHP < 0 && c.toLatin1() == '\'' && stringBExpect < 0) {
|
|
stringSQOpenedPHP = -1;
|
|
state = STATE_NONE;
|
|
stringEscStringPHP = "";
|
|
stringBExpect = STATE_STRING_NOWDOC;
|
|
} else if (!opened && stringBstring.size()==3 && stringBlock.size()==0 && isAlpha) {
|
|
stringBlock = c;
|
|
if (isLast && stringBExpect < 0) {
|
|
stringBstring = "";
|
|
stringBOpened = pos;
|
|
stringBExpect = -1;
|
|
state = STATE_STRING_HEREDOC;
|
|
return true;
|
|
}
|
|
} else if (!opened && stringBstring.size()==3 && stringBlock.size()>0 && isAlnum) {
|
|
stringBlock += c;
|
|
if (isLast && stringBExpect < 0) {
|
|
stringBstring = "";
|
|
stringBOpened = pos;
|
|
stringBExpect = -1;
|
|
state = STATE_STRING_HEREDOC;
|
|
return true;
|
|
}
|
|
} else if (!opened && stringBstring.size()==3 && stringBlock.size()>0 && stringSQOpenedPHP < 0 && stringBExpect == STATE_STRING_HEREDOC && c.toLatin1() == '"' && isLast) {
|
|
stringDQOpenedPHP = -1;
|
|
stringEscStringPHP = "";
|
|
stringBExpect = -1;
|
|
stringBstring = "";
|
|
stringBOpened = pos;
|
|
state = STATE_STRING_HEREDOC;
|
|
return true;
|
|
} else if (!opened && stringBstring.size()==3 && stringBlock.size()>0 && stringDQOpenedPHP < 0 && stringBExpect == STATE_STRING_NOWDOC && c.toLatin1() == '\'' && isLast) {
|
|
stringSQOpenedPHP = -1;
|
|
stringEscStringPHP = "";
|
|
stringBExpect = -1;
|
|
stringBstring = "";
|
|
stringBOpened = pos;
|
|
state = STATE_STRING_NOWDOC;
|
|
return true;
|
|
} else if (stringBOpened>=0 && stringBlock.size()>0) {
|
|
stringBstring += c;
|
|
if (stringBstring == stringBlock+";" && isLast) {
|
|
stringBstring = "";
|
|
stringBlock = "";
|
|
stringBOpened = -1;
|
|
stringBExpect = -1;
|
|
state = STATE_NONE;
|
|
return true;
|
|
}
|
|
} else {
|
|
stringBstring = "";
|
|
stringBlock = "";
|
|
stringBStart = -1;
|
|
stringBExpect = -1;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectRegexpJS(const QChar & c, int pos, bool isWSPace, bool isAlnum)
|
|
{
|
|
bool opened = stringSQOpenedJS >= 0 || stringDQOpenedJS >= 0 || commentSLOpenedJS >= 0 || commentMLOpenedJS >= 0 || regexpOpenedJS >= 0 || exprOpenedJS >= 0;
|
|
if (!opened && c.toLatin1() == '/' && regexpPrevCharJS.size()==0) {
|
|
regexpOpenedJS = pos;
|
|
prevPrevState = prevState;
|
|
prevState = state;
|
|
state = STATE_REGEXP_JS;
|
|
regexpEscStringJS = "";
|
|
regexpPrevCharJS = "";
|
|
return true;
|
|
} else if (regexpOpenedJS >= 0 && c.toLatin1() == '/' && regexpEscStringJS.size()%2 == 0) {
|
|
regexpOpenedJS = -1;
|
|
state = prevState;
|
|
prevState = prevPrevState;
|
|
prevPrevState = STATE_NONE;
|
|
regexpEscStringJS = "";
|
|
regexpPrevCharJS = "";
|
|
return true;
|
|
} else if (regexpOpenedJS >= 0 && c.toLatin1() == '\\') {
|
|
regexpEscStringJS += c;
|
|
} else if (regexpOpenedJS >= 0) {
|
|
if (c.toLatin1() == '<') prevRegexpEscStringJS = regexpEscStringJS;
|
|
regexpEscStringJS = "";
|
|
} else if (regexpOpenedJS < 0 && !isWSPace && (isAlnum || c.toLatin1() == '$' || c.toLatin1() == ')' || c.toLatin1() == ']' || c.toLatin1() == '<' || c.toLatin1() == '~')) {
|
|
regexpPrevCharJS = c;
|
|
} else if (regexpOpenedJS < 0 && !isWSPace) {
|
|
regexpPrevCharJS = "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int Highlight::detectKeywordHTML(const QChar & c, int pos, bool isAlpha, bool isAlnum, bool isLast) {
|
|
bool opened = stringSQOpenedHTML >= 0 || stringDQOpenedHTML >= 0 || commentHTMLOpened >= 0 || keywordHTMLOpened >= 0;
|
|
if (!opened && keywordHTMLOpened!=-2 && isAlnum && !isAlpha) {
|
|
keywordHTMLOpened = -2;
|
|
} else if (!opened && keywordHTMLOpened==-2 && !isAlnum) {
|
|
keywordHTMLOpened = -1;
|
|
keywordHTMLprevPrevChar = keywordHTMLprevChar;
|
|
keywordHTMLprevChar = c;
|
|
} else if (!opened && keywordHTMLOpened!=-2 && isAlpha) {
|
|
keywordStringHTML = c;
|
|
keywordHTMLOpened = pos;
|
|
} else if (keywordHTMLOpened>=0 && isAlnum) {
|
|
keywordStringHTML += c;
|
|
} else if (keywordHTMLOpened<0) {
|
|
keywordHTMLprevPrevChar = keywordHTMLprevChar;
|
|
keywordHTMLprevChar = c;
|
|
}
|
|
if (keywordHTMLOpened>=0 && (!isAlnum || isLast)) {
|
|
int kOpened = keywordHTMLOpened;
|
|
keywordHTMLOpened = -1;
|
|
return kOpened;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int Highlight::detectKeywordCSS(const QChar & c, int pos, bool isAlpha, bool isAlnum, bool isLast) {
|
|
if (!isAlpha && c.toLatin1() == '-') isAlpha = true;
|
|
if (!isAlnum && c.toLatin1() == '-') isAlnum = true;
|
|
if (!isAlpha && isAlnum && keywordCSSprevChar == "#") isAlpha = true;
|
|
bool opened = stringSQOpenedCSS >= 0 || stringDQOpenedCSS >= 0 || commentMLOpenedCSS >= 0 || keywordCSSOpened >= 0;
|
|
if (!opened && keywordCSSOpened!=-2 && isAlnum && !isAlpha) {
|
|
keywordCSSOpened = -2;
|
|
} else if (!opened && keywordCSSOpened==-2 && !isAlnum) {
|
|
keywordCSSOpened = -1;
|
|
keywordCSSprevPrevChar = keywordCSSprevChar;
|
|
keywordCSSprevChar = c;
|
|
} else if (!opened && keywordCSSOpened!=-2 && isAlpha) {
|
|
keywordStringCSS = c;
|
|
keywordCSSOpened = pos;
|
|
if (keywordCSSprevChar == "#") isColorKeyword = true;
|
|
else isColorKeyword = false;
|
|
} else if (keywordCSSOpened>=0 && isAlnum) {
|
|
keywordStringCSS += c;
|
|
} else if (keywordCSSOpened<0) {
|
|
keywordCSSprevPrevChar = keywordCSSprevChar;
|
|
keywordCSSprevChar = c;
|
|
}
|
|
if (keywordCSSOpened>=0 && isColorKeyword && isAlnum && !isdigit(c.toLatin1())) {
|
|
QChar _c = c.toLower();
|
|
if (_c.toLatin1() != 'a' && _c.toLatin1() != 'b' && _c.toLatin1() != 'c' && _c.toLatin1() != 'd' && _c.toLatin1() != 'e' && _c.toLatin1() != 'f') isColorKeyword = false;
|
|
}
|
|
if (keywordCSSOpened>=0 && (!isAlnum || isLast)) {
|
|
int kOpened = keywordCSSOpened;
|
|
keywordCSSOpened = -1;
|
|
return kOpened;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int Highlight::detectKeywordJS(const QChar & c, int pos, bool isAlpha, bool isAlnum, bool isLast) {
|
|
if (!isAlpha && c.toLatin1() == '$') isAlpha = true;
|
|
if (!isAlnum && c.toLatin1() == '$') isAlnum = true;
|
|
bool opened = stringSQOpenedJS >= 0 || stringDQOpenedJS >= 0 || commentSLOpenedJS >= 0 || commentMLOpenedJS >= 0 || regexpOpenedJS >= 0 || keywordJSOpened >= 0 || exprOpenedJS >= 0;
|
|
if (!opened && keywordJSOpened!=-2 && isAlnum && !isAlpha) {
|
|
keywordJSOpened = -2;
|
|
} else if (!opened && keywordJSOpened==-2 && !isAlnum) {
|
|
keywordJSOpened = -1;
|
|
keywordJSprevChar = c;
|
|
} else if (!opened && keywordJSOpened!=-2 && isAlpha) {
|
|
keywordStringJS = c;
|
|
keywordJSOpened = pos;
|
|
} else if (keywordJSOpened>=0 && isAlnum) {
|
|
keywordStringJS += c;
|
|
} else if (keywordJSOpened<0) {
|
|
keywordJSprevChar = c;
|
|
}
|
|
if (keywordJSOpened>=0 && (!isAlnum || isLast)) {
|
|
int kOpened = keywordJSOpened;
|
|
keywordJSOpened = -1;
|
|
return kOpened;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int Highlight::detectKeywordPHP(const QChar & c, int pos, bool isAlpha, bool isAlnum, bool isLast, bool forceDetect) {
|
|
bool opened = stringSQOpenedPHP >= 0 || stringDQOpenedPHP >= 0 || stringBOpened >= 0 || commentSLOpenedPHP >= 0 || commentMLOpenedPHP >= 0 || keywordPHPOpened >= 0 || exprOpenedPHP >= 0;
|
|
if (forceDetect && keywordPHPOpened<0) opened = false;
|
|
if (!opened && keywordPHPOpened!=-2 && isAlnum && !isAlpha) {
|
|
keywordPHPOpened = -2;
|
|
} else if (!opened && keywordPHPOpened==-2 && !isAlnum) {
|
|
keywordPHPOpened = -1;
|
|
keywordPHPprevPrevChar = keywordPHPprevChar;
|
|
keywordPHPprevChar = c;
|
|
} else if (!opened && keywordPHPOpened!=-2 && isAlpha) {
|
|
keywordStringPHP = c;
|
|
keywordPHPOpened = pos;
|
|
} else if (keywordPHPOpened>=0 && isAlnum) {
|
|
keywordStringPHP += c;
|
|
} else if (keywordPHPOpened<0) {
|
|
keywordPHPprevPrevChar = keywordPHPprevChar;
|
|
keywordPHPprevChar = c;
|
|
}
|
|
if (keywordPHPOpened>=0 && (!isAlnum || isLast)) {
|
|
int kOpened = keywordPHPOpened;
|
|
keywordPHPOpened = -1;
|
|
return kOpened;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
bool Highlight::detectExpressionJS(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedJS >= 0 || stringDQOpenedJS >= 0 || commentSLOpenedJS >= 0 || commentMLOpenedJS >= 0 || regexpOpenedJS >= 0 || exprOpenedJS >= 0;
|
|
if (!opened && c.toLatin1() == '`') {
|
|
exprOpenedJS = pos;
|
|
prevPrevState = prevState;
|
|
prevState = state;
|
|
state = STATE_EXPRESSION_JS;
|
|
exprEscStringJS = "";
|
|
return true;
|
|
} else if (exprOpenedJS >= 0 && c.toLatin1() == '`' && exprEscStringJS.size()%2 == 0) {
|
|
exprOpenedJS = -1;
|
|
state = prevState;
|
|
prevState = prevPrevState;
|
|
prevPrevState = STATE_NONE;
|
|
exprEscStringJS = "";
|
|
return true;
|
|
} else if (exprOpenedJS >= 0 && c.toLatin1() == '\\') {
|
|
exprEscStringJS += c;
|
|
} else if (exprOpenedJS >= 0) {
|
|
if (c.toLatin1() == '<') prevExprEscStringJS = exprEscStringJS;
|
|
exprEscStringJS = "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectExpressionPHP(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedPHP >= 0 || stringDQOpenedPHP >= 0 || stringBOpened >= 0 || commentSLOpenedPHP >= 0 || commentMLOpenedPHP >= 0 || exprOpenedPHP >= 0;
|
|
if (!opened && c.toLatin1() == '`') {
|
|
exprOpenedPHP = pos;
|
|
state = STATE_EXPRESSION_PHP;
|
|
exprEscStringPHP = "";
|
|
return true;
|
|
} else if (exprOpenedPHP >= 0 && c.toLatin1() == '`' && exprEscStringPHP.size()%2 == 0) {
|
|
exprOpenedPHP = -1;
|
|
state = STATE_NONE;
|
|
exprEscStringPHP = "";
|
|
return true;
|
|
} else if (exprOpenedPHP >= 0 && c.toLatin1() == '\\') {
|
|
exprEscStringPHP += c;
|
|
} else if (exprOpenedPHP >= 0) {
|
|
exprEscStringPHP = "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectStringSQUnknown(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedUnknown >= 0 || stringDQOpenedUnknown >= 0 || commentSLOpenedUnknown >= 0 || commentMLOpenedUnknown >= 0;
|
|
if (!opened && c.toLatin1() == '\'') {
|
|
stringSQOpenedUnknown = pos;
|
|
state = STATE_STRING_SQ_UNKNOWN;
|
|
stringEscStringUnknown = "";
|
|
return true;
|
|
} else if (stringSQOpenedUnknown >= 0 && c.toLatin1() == '\'' && stringEscStringUnknown.size()%2 == 0) {
|
|
stringSQOpenedUnknown = -1;
|
|
state = STATE_NONE;
|
|
stringEscStringUnknown = "";
|
|
return true;
|
|
} else if (stringSQOpenedUnknown >= 0 && c.toLatin1() == '\\') {
|
|
stringEscStringUnknown += c;
|
|
} else if (stringSQOpenedUnknown >= 0) {
|
|
stringEscStringUnknown = "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectStringDQUnknown(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedUnknown >= 0 || stringDQOpenedUnknown >= 0 || commentSLOpenedUnknown >= 0 || commentMLOpenedUnknown >= 0;
|
|
if (!opened && c.toLatin1() == '"') {
|
|
stringDQOpenedUnknown = pos;
|
|
state = STATE_STRING_DQ_UNKNOWN;
|
|
stringEscStringUnknown = "";
|
|
return true;
|
|
} else if (stringDQOpenedUnknown >= 0 && c.toLatin1() == '"' && stringEscStringUnknown.size()%2 == 0) {
|
|
stringDQOpenedUnknown = -1;
|
|
state = STATE_NONE;
|
|
stringEscStringUnknown = "";
|
|
return true;
|
|
} else if (stringDQOpenedUnknown >= 0 && c.toLatin1() == '\\') {
|
|
stringEscStringUnknown += c;
|
|
} else if (stringDQOpenedUnknown >= 0) {
|
|
stringEscStringUnknown = "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectSLCommentUnknown(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedUnknown >= 0 || stringDQOpenedUnknown >= 0 || commentSLOpenedUnknown >= 0 || commentMLOpenedUnknown >= 0;
|
|
if (!opened && commentUnknownStringSL.size()==0 && (c.toLatin1() == '/' || c.toLatin1() == '#' || (c.toLatin1() == ';' && extension == EXTENSION_INI))) {
|
|
if (c.toLatin1() == '#' || (c.toLatin1() == ';' && extension == EXTENSION_INI)) {
|
|
commentUnknownStringSL = "";
|
|
commentSLOpenedUnknown = pos;
|
|
state = STATE_COMMENT_SL_UNKNOWN;
|
|
return true;
|
|
} else {
|
|
commentUnknownStringSL = c;
|
|
}
|
|
} else if (!opened && commentUnknownStringSL.size()==1) {
|
|
commentUnknownStringSL += c;
|
|
if (commentUnknownStringSL=="//") {
|
|
commentUnknownStringSL = "";
|
|
commentSLOpenedUnknown = pos;
|
|
state = STATE_COMMENT_SL_UNKNOWN;
|
|
return true;
|
|
} else {
|
|
commentUnknownStringSL = "";
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Highlight::detectMLCommentUnknown(const QChar & c, int pos)
|
|
{
|
|
bool opened = stringSQOpenedUnknown >= 0 || stringDQOpenedUnknown >= 0 || commentSLOpenedUnknown >= 0 || commentMLOpenedUnknown >= 0;
|
|
if (!opened && commentUnknownStringML.size()==0 && c.toLatin1() == '/') {
|
|
commentUnknownStringML = c;
|
|
} else if (!opened && commentUnknownStringML.size()==1) {
|
|
commentUnknownStringML += c;
|
|
if (commentUnknownStringML=="/*") {
|
|
commentUnknownStringML = "";
|
|
commentMLOpenedUnknown = pos;
|
|
state = STATE_COMMENT_ML_UNKNOWN;
|
|
return true;
|
|
} else {
|
|
commentUnknownStringML = "";
|
|
}
|
|
} else if (commentMLOpenedUnknown >= 0 && c.toLatin1() == '*') {
|
|
commentUnknownStringML = c;
|
|
} else if (commentMLOpenedUnknown >= 0 && commentUnknownStringML.size()==1) {
|
|
commentUnknownStringML += c;
|
|
if (commentUnknownStringML == "*/") {
|
|
commentUnknownStringML = "";
|
|
commentMLOpenedUnknown = -1;
|
|
state = STATE_NONE;
|
|
return true;
|
|
} else {
|
|
commentUnknownStringML = "";
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int Highlight::detectKeywordUnknown(const QChar & c, int pos, bool isAlpha, bool isAlnum, bool isLast) {
|
|
if (!isAlpha && c.toLatin1() == '-') isAlpha = true;
|
|
if (!isAlnum && c.toLatin1() == '-') isAlnum = true;
|
|
bool opened = stringSQOpenedUnknown >= 0 || stringDQOpenedUnknown >= 0 || commentSLOpenedUnknown >= 0 || commentMLOpenedUnknown >= 0 || keywordUnknownOpened >= 0;
|
|
if (!opened && keywordUnknownOpened!=-2 && isAlnum && !isAlpha) {
|
|
keywordUnknownOpened = -2;
|
|
} else if (!opened && keywordUnknownOpened==-2 && !isAlnum) {
|
|
keywordUnknownOpened = -1;
|
|
keywordUnknownprevChar = c;
|
|
} else if (!opened && keywordUnknownOpened!=-2 && isAlpha) {
|
|
keywordStringUnknown = c;
|
|
keywordUnknownOpened = pos;
|
|
} else if (keywordUnknownOpened>=0 && isAlnum) {
|
|
keywordStringUnknown += c;
|
|
} else if (keywordUnknownOpened<0) {
|
|
keywordUnknownprevChar = c;
|
|
}
|
|
if (keywordUnknownOpened>=0 && (!isAlnum || isLast)) {
|
|
int kOpened = keywordUnknownOpened;
|
|
keywordUnknownOpened = -1;
|
|
return kOpened;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void Highlight::restoreState() {
|
|
// load previous block data
|
|
QTextCursor curs = QTextCursor(cBlock);
|
|
if (curs.movePosition(QTextCursor::MoveOperation::PreviousBlock)) {
|
|
HighlightData * prevBlockData = dynamic_cast<HighlightData *>(curs.block().userData());
|
|
if (prevBlockData != nullptr) {
|
|
state = prevBlockData->state;
|
|
prevState = prevBlockData->prevState;
|
|
prevPrevState = prevBlockData->prevPrevState;
|
|
mode = prevBlockData->mode.toStdString();
|
|
prevMode = prevBlockData->prevMode.toStdString();
|
|
modeExpect = prevBlockData->modeExpect.toStdString();
|
|
if (modeExpect.size()>0) {
|
|
modeString = prevBlockData->modeString;
|
|
modeSpos = 0;
|
|
modeSkip = true;
|
|
}
|
|
prevModeExpect = prevBlockData->prevModeExpect.toStdString();
|
|
prevModeString = prevBlockData->prevModeString;
|
|
prevModeSkip = prevBlockData->prevModeSkip;
|
|
if (prevModeString.size()>0) {
|
|
prevModeSpos = 0;
|
|
}
|
|
modeExpectC = prevBlockData->modeExpectC.toStdString();
|
|
if (modeExpectC.size()>0) {
|
|
modeStringC = prevBlockData->modeStringC;
|
|
modeCpos = 0;
|
|
modeSkipC = true;
|
|
}
|
|
prevModeExpectC = prevBlockData->prevModeExpectC.toStdString();
|
|
prevModeStringC = prevBlockData->prevModeStringC;
|
|
prevModeSkipC = prevBlockData->prevModeSkipC;
|
|
if (prevModeStringC.size()>0) {
|
|
prevModeCpos = 0;
|
|
}
|
|
stringEscStringCSS = prevBlockData->stringEscStringCSS;
|
|
stringEscStringJS = prevBlockData->stringEscStringJS;
|
|
stringBlock = prevBlockData->stringBlock;
|
|
regexpEscStringJS = prevBlockData->regexpEscStringJS;
|
|
regexpPrevCharJS = prevBlockData->regexpPrevCharJS;
|
|
bracesCSS = prevBlockData->bracesCSS;
|
|
bracesJS = prevBlockData->bracesJS;
|
|
bracesPHP = prevBlockData->bracesPHP;
|
|
parensCSS = prevBlockData->parensCSS;
|
|
parensJS = prevBlockData->parensJS;
|
|
parensPHP = prevBlockData->parensPHP;
|
|
cssMediaScope = prevBlockData->cssMediaScope;
|
|
keywordPHPScoped = prevBlockData->keywordPHPScoped;
|
|
keywordJSScoped = prevBlockData->keywordJSScoped;
|
|
exprEscStringJS = prevBlockData->exprEscStringJS;
|
|
stringEscVariableJS = prevBlockData->stringEscVariableJS;
|
|
nsNamePHP = prevBlockData->nsNamePHP;
|
|
nsChainPHP = prevBlockData->nsChainPHP;
|
|
nsScopeChainPHP = prevBlockData->nsScopeChainPHP;
|
|
clsNamePHP = prevBlockData->clsNamePHP;
|
|
clsChainPHP = prevBlockData->clsChainPHP;
|
|
clsScopeChainPHP = prevBlockData->clsScopeChainPHP;
|
|
funcNamePHP = prevBlockData->funcNamePHP;
|
|
funcChainPHP = prevBlockData->funcChainPHP;
|
|
funcScopeChainPHP = prevBlockData->funcScopeChainPHP;
|
|
expectedNsNamePHP = prevBlockData->expectedNsNamePHP;
|
|
expectedClsNamePHP = prevBlockData->expectedClsNamePHP;
|
|
expectedFuncNamePHP = prevBlockData->expectedFuncNamePHP;
|
|
expectedFuncParsPHP = prevBlockData->expectedFuncParsPHP;
|
|
expectedFuncArgsPHP = prevBlockData->expectedFuncArgsPHP;
|
|
expectedFuncArgsPHPPositions = prevBlockData->expectedFuncArgsPHPPositions;
|
|
expectedFuncArgsPHPBlocks = prevBlockData->expectedFuncArgsPHPBlocks;
|
|
nsScopePHP = prevBlockData->nsScopePHP;
|
|
clsScopePHP = prevBlockData->clsScopePHP;
|
|
funcScopePHP = prevBlockData->funcScopePHP;
|
|
varsChainsPHP = prevBlockData->varsChainsPHP;
|
|
usedVarsChainsPHP = prevBlockData->usedVarsChainsPHP;
|
|
varsGlobChainPHP = prevBlockData->varsGlobChainPHP;
|
|
usedVarsGlobChainPHP = prevBlockData->usedVarsGlobChainPHP;
|
|
varsClsChainPHP = prevBlockData->varsClsChainPHP;
|
|
varsChainPHP = prevBlockData->varsChainPHP;
|
|
usedVarsChainPHP = prevBlockData->usedVarsChainPHP;
|
|
clsOpenPHP = prevBlockData->clsOpenPHP;
|
|
clsOpensPHP = prevBlockData->clsOpensPHP;
|
|
varsClsOpenChainPHP = prevBlockData->varsClsOpenChainPHP;
|
|
clsPropsChainPHP = prevBlockData->clsPropsChainPHP;
|
|
isGlobalPHP = prevBlockData->isGlobalPHP;
|
|
funcNameJS = prevBlockData->funcNameJS;
|
|
funcScopeChainJS = prevBlockData->funcScopeChainJS;
|
|
funcChainJS = prevBlockData->funcChainJS;
|
|
expectedFuncNameJS = prevBlockData->expectedFuncNameJS;
|
|
expectedFuncVarJS = prevBlockData->expectedFuncVarJS;
|
|
expectedFuncParsJS = prevBlockData->expectedFuncParsJS;
|
|
funcScopeJS = prevBlockData->funcScopeJS;
|
|
varsChainJS = prevBlockData->varsChainJS;
|
|
expectedFuncArgsJS = prevBlockData->expectedFuncArgsJS;
|
|
mediaNameCSS = prevBlockData->mediaNameCSS;
|
|
expectedMediaNameCSS = prevBlockData->expectedMediaNameCSS;
|
|
expectedMediaParsCSS = prevBlockData->expectedMediaParsCSS;
|
|
mediaScopeCSS = prevBlockData->mediaScopeCSS;
|
|
tagChainHTML = prevBlockData->tagChainHTML;
|
|
keywordPHPprevString = prevBlockData->keywordPHPprevString;
|
|
keywordPHPprevStringPrevChar = prevBlockData->keywordPHPprevStringPrevChar;
|
|
keywordJSprevString = prevBlockData->keywordJSprevString;
|
|
keywordJSprevStringPrevChar = prevBlockData->keywordJSprevStringPrevChar;
|
|
cssNamesChain = prevBlockData->cssNamesChain;
|
|
operatorsChainPHP = prevBlockData->operatorsChainPHP;
|
|
operatorsPHP = prevBlockData->operatorsPHP;
|
|
operatorsChainJS = prevBlockData->operatorsChainJS;
|
|
operatorsJS = prevBlockData->operatorsJS;
|
|
expectedClsNameJS = prevBlockData->expectedClsNameJS;
|
|
clsNameJS = prevBlockData->clsNameJS;
|
|
clsScopeJS = prevBlockData->clsScopeJS;
|
|
clsChainJS = prevBlockData->clsChainJS;
|
|
clsScopeChainJS = prevBlockData->clsScopeChainJS;
|
|
clsOpensJS = prevBlockData->clsOpensJS;
|
|
clsOpenJS = prevBlockData->clsOpenJS;
|
|
}
|
|
}
|
|
|
|
if (state == STATE_TAG || prevState == STATE_TAG || prevPrevState == STATE_TAG) {
|
|
tagOpened = 0;
|
|
}
|
|
if (state == STATE_COMMENT_ML_HTML || prevState == STATE_COMMENT_ML_HTML) {
|
|
tagOpened = 0;
|
|
commentHTMLOpened = 0;
|
|
}
|
|
if (state == STATE_STRING_SQ_HTML || prevState == STATE_STRING_SQ_HTML) {
|
|
stringSQOpenedHTML = 0;
|
|
}
|
|
if (state == STATE_STRING_DQ_HTML || prevState == STATE_STRING_DQ_HTML) {
|
|
stringDQOpenedHTML = 0;
|
|
}
|
|
if (state == STATE_STRING_SQ_CSS || prevState == STATE_STRING_SQ_CSS) {
|
|
stringSQOpenedCSS = 0;
|
|
}
|
|
if (state == STATE_STRING_DQ_CSS || prevState == STATE_STRING_DQ_CSS) {
|
|
stringDQOpenedCSS = 0;
|
|
}
|
|
if (state == STATE_STRING_SQ_JS || prevState == STATE_STRING_SQ_JS) {
|
|
stringSQOpenedJS = 0;
|
|
}
|
|
if (state == STATE_STRING_DQ_JS || prevState == STATE_STRING_DQ_JS) {
|
|
stringDQOpenedJS = 0;
|
|
}
|
|
if (state == STATE_REGEXP_JS || prevState == STATE_REGEXP_JS) {
|
|
regexpOpenedJS = 0;
|
|
}
|
|
if (state == STATE_COMMENT_ML_JS || prevState == STATE_COMMENT_ML_JS) {
|
|
commentMLOpenedJS = 0;
|
|
}
|
|
if (state == STATE_COMMENT_SL_JS) {
|
|
state = STATE_NONE;
|
|
}
|
|
if (prevState == STATE_COMMENT_SL_JS) {
|
|
commentSLOpenedJS = 0;
|
|
}
|
|
if (state == STATE_COMMENT_ML_CSS || prevState == STATE_COMMENT_ML_CSS) {
|
|
commentMLOpenedCSS = 0;
|
|
}
|
|
if (state == STATE_STRING_SQ_PHP) {
|
|
stringSQOpenedPHP = 0;
|
|
}
|
|
if (state == STATE_STRING_DQ_PHP) {
|
|
stringDQOpenedPHP = 0;
|
|
}
|
|
if (state == STATE_COMMENT_ML_PHP) {
|
|
commentMLOpenedPHP = 0;
|
|
}
|
|
if (state == STATE_COMMENT_SL_PHP) {
|
|
state = STATE_NONE;
|
|
}
|
|
if (state == STATE_STRING_HEREDOC || state == STATE_STRING_NOWDOC) {
|
|
stringBOpened = 0;
|
|
}
|
|
if (keywordPHPScoped) {
|
|
keywordPHPScopedOpened = 0;
|
|
}
|
|
if (keywordJSScoped) {
|
|
keywordJSScopedOpened = 0;
|
|
}
|
|
if (state == STATE_EXPRESSION_PHP) {
|
|
exprOpenedPHP = 0;
|
|
}
|
|
if (state == STATE_EXPRESSION_JS || prevState == STATE_EXPRESSION_JS) {
|
|
exprOpenedJS = 0;
|
|
}
|
|
if (state == STATE_STRING_SQ_UNKNOWN) {
|
|
stringSQOpenedUnknown = 0;
|
|
}
|
|
if (state == STATE_STRING_DQ_UNKNOWN) {
|
|
stringDQOpenedUnknown = 0;
|
|
}
|
|
if (state == STATE_COMMENT_ML_UNKNOWN) {
|
|
commentMLOpenedUnknown = 0;
|
|
}
|
|
if (state == STATE_COMMENT_SL_UNKNOWN) {
|
|
state = STATE_NONE;
|
|
}
|
|
}
|
|
|
|
void Highlight::highlightSpell()
|
|
{
|
|
if (blockData != nullptr && blockData->spellStarts.size() == blockData->spellLengths.size()) {
|
|
for (int i=0; i<blockData->spellStarts.size(); i++) {
|
|
int start = blockData->spellStarts.at(i);
|
|
int length = blockData->spellLengths.at(i);
|
|
if (start < 0 || length <= 0) continue;
|
|
QTextCharFormat uFormat = format(start);
|
|
uFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
|
|
uFormat.setUnderlineColor(spellColor);
|
|
highlightString(start, length, uFormat);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Highlight::highlightError(int pos, int length)
|
|
{
|
|
if (pos < 0 || length < 1) return;
|
|
QTextCharFormat uFormat = format(pos);
|
|
uFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
|
|
uFormat.setUnderlineColor(errorColor);
|
|
highlightString(pos, length, uFormat);
|
|
}
|
|
|
|
bool Highlight::parseMode(const QChar & c, int pos, bool isWSpace, bool isLast, std::string & pMode, int & pState)
|
|
{
|
|
if (modeType != MODE_MIXED || !detectMode(c, pos, isWSpace, isLast)) return false;
|
|
if (modeSpos>=0 && modeCpos<0) {
|
|
prevPrevState = prevState;
|
|
prevState = state;
|
|
state = STATE_NONE;
|
|
if (tagOpened == modeSpos) {
|
|
tagOpened = -1;
|
|
if (prevState == STATE_TAG) prevState = STATE_NONE;
|
|
}
|
|
if (prevState == STATE_STRING_SQ_CSS || prevState == STATE_STRING_DQ_CSS) {
|
|
stringEscStringCSS = prevStringEscStringCSS;
|
|
prevStringEscStringCSS = "";
|
|
}
|
|
if (prevState == STATE_STRING_SQ_JS || prevState == STATE_STRING_DQ_JS) {
|
|
stringEscStringJS = prevStringEscStringJS;
|
|
prevStringEscStringJS = "";
|
|
}
|
|
if (prevState == STATE_REGEXP_JS) {
|
|
regexpEscStringJS = prevRegexpEscStringJS;
|
|
prevRegexpEscStringJS = "";
|
|
}
|
|
if (prevState == STATE_EXPRESSION_JS) {
|
|
exprEscStringJS = prevExprEscStringJS;
|
|
prevExprEscStringJS = "";
|
|
stringEscVariableJS = prevStringEscVariableJS;
|
|
prevStringEscVariableJS = "";
|
|
}
|
|
|
|
pMode = mode;
|
|
// highlight tag
|
|
if (mode == MODE_PHP) {
|
|
highlightString(modeSpos, pos-modeSpos+1, HW->phpTagFormat);
|
|
} else if (mode == MODE_JS || mode == MODE_CSS) {
|
|
highlightChar(pos, HW->tagFormat);
|
|
}
|
|
|
|
QString modeTag = "";
|
|
if (mode == MODE_CSS) modeTag = "style";
|
|
else if (mode == MODE_JS) modeTag = "script";
|
|
if (modeTag.size() > 0) {
|
|
addSpecialWord(modeTag, modeSpos+1);
|
|
// open tag chain
|
|
if (tagChainStartsHTML.size() > tagChainEndsHTML.size()) {
|
|
tagChainEndsHTML.append(modeSpos);
|
|
}
|
|
if (tagChainHTML.size() > 0) tagChainHTML += ",";
|
|
tagChainHTML += modeTag;
|
|
tagChainStartsHTML.append(modeSpos+1);
|
|
tagChainsHTML.append(tagChainHTML);
|
|
}
|
|
|
|
if (modeStarts.size()>modeEnds.size()) {
|
|
modeEnds.append(modeSpos);
|
|
}
|
|
modeStarts.append(pos+1);
|
|
modeTags.append(mode);
|
|
|
|
if (stateStarts.size()>stateEnds.size()) {
|
|
stateEnds.append(modeSpos);
|
|
}
|
|
pState = state;
|
|
|
|
modeSpos = -1;
|
|
modeCpos = -1;
|
|
|
|
if (!foundModes.contains(QString::fromStdString(mode))) foundModes.append(QString::fromStdString(mode));
|
|
} else if (modeSpos<0 && modeCpos>=0) {
|
|
state = prevState;
|
|
prevState = prevPrevState;
|
|
prevPrevState = STATE_NONE;
|
|
|
|
// highlight tag
|
|
if (pMode == MODE_PHP) {
|
|
highlightString(modeCpos, pos-modeCpos+1, HW->phpTagFormat);
|
|
} else if ((pMode == MODE_JS || pMode == MODE_CSS) && modeCposed == modeCpos) {
|
|
highlightString(modeCpos, pos-modeCpos+1, HW->tagFormat);
|
|
}
|
|
|
|
QString modeTag = "";
|
|
if (pMode == MODE_CSS) modeTag = "style";
|
|
else if (pMode == MODE_JS) modeTag = "script";
|
|
if (modeTag.size() > 0) {
|
|
addSpecialWord("/"+modeTag, modeCpos+2);
|
|
// close tag chain
|
|
if (tagChainHTML.size() > 0) {
|
|
QStringList tagChainList = tagChainHTML.split(",");
|
|
QString lastTag = tagChainList.last();
|
|
if (lastTag == modeTag) {
|
|
tagChainList.removeLast();
|
|
tagChainEndsHTML.append(modeCpos+modeTag.size()+2);
|
|
QString tagChainN = "";
|
|
for (int i=0; i<tagChainList.size(); i++) {
|
|
if (tagChainN.size() > 0) tagChainN += ",";
|
|
tagChainN += tagChainList.at(i);
|
|
}
|
|
if (tagChainN.size() > 0) {
|
|
tagChainStartsHTML.append(modeCpos+modeTag.size()+3);
|
|
tagChainsHTML.append(tagChainN);
|
|
}
|
|
tagChainHTML = tagChainN;
|
|
}
|
|
}
|
|
}
|
|
|
|
// close single line comments
|
|
if (pMode == MODE_PHP && commentSLOpenedPHP>=0) {
|
|
commentPHPStringSL = "";
|
|
commentSLOpenedPHP = -1;
|
|
}
|
|
if (pMode == MODE_JS && commentSLOpenedJS>=0) {
|
|
commentJSStringSL = "";
|
|
commentSLOpenedJS = -1;
|
|
}
|
|
pMode = mode;
|
|
|
|
modeEnds.append(modeCpos);
|
|
if (mode != MODE_HTML) {
|
|
modeStarts.append(pos+1);
|
|
modeTags.append(mode);
|
|
}
|
|
|
|
if (stateStarts.size()>stateEnds.size()) {
|
|
stateEnds.append(modeCpos);
|
|
}
|
|
if (state != STATE_NONE) {
|
|
stateStarts.append(pos+1);
|
|
stateIds.append(state);
|
|
}
|
|
pState = state;
|
|
|
|
modeString = prevModeString;
|
|
modeExpect = prevModeExpect;
|
|
modeSkip = prevModeSkip;
|
|
modeSpos = prevModeSpos;
|
|
modeStringC = prevModeStringC;
|
|
modeExpectC = prevModeExpectC;
|
|
modeSkipC = prevModeSkipC;
|
|
modeCpos = prevModeCpos;
|
|
|
|
if (!foundModes.contains(QString::fromStdString(mode))) foundModes.append(QString::fromStdString(mode));
|
|
} else {
|
|
modeSpos = -1;
|
|
modeCpos = -1;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Highlight::parseHTML(const QChar & c, const QChar & prevC, int pos, bool isAlpha, bool isAlnum, bool isLast)
|
|
{
|
|
if (mode != MODE_HTML) return;
|
|
bool tagChanged = detectTag(c, pos);
|
|
if (tagOpened>=0 || tagChanged) {
|
|
highlightChar(pos, HW->tagFormat);
|
|
}
|
|
|
|
// html comments
|
|
bool commentHTMLchanged = detectCommentHTML(c);
|
|
if (commentHTMLOpened>=0 && commentHTMLchanged) {
|
|
highlightString(commentHTMLOpened, pos-commentHTMLOpened+1, HW->multiLineCommentFormat);
|
|
} else if (commentHTMLOpened<0 && commentHTMLchanged) {
|
|
highlightChar(pos, HW->multiLineCommentFormat);
|
|
} else if (commentHTMLOpened>=0) {
|
|
highlightChar(pos, HW->multiLineCommentFormat);
|
|
}
|
|
|
|
// html string (single quote)
|
|
bool stringSQchangedHTML = detectStringSQHTML(c, pos);
|
|
if ((stringSQOpenedHTML>=0 && state == STATE_STRING_SQ_HTML) || stringSQchangedHTML) {
|
|
highlightChar(pos, HW->stringFormat);
|
|
}
|
|
|
|
// html string (double quote)
|
|
bool stringDQchangedHTML = detectStringDQHTML(c, pos);
|
|
if ((stringDQOpenedHTML>=0 && state == STATE_STRING_DQ_HTML)|| stringDQchangedHTML) {
|
|
highlightChar(pos, HW->stringFormat);
|
|
}
|
|
|
|
// html tag keywords
|
|
int keywordHTMLStart = detectKeywordHTML(c, pos, isAlpha, isAlnum, isLast);
|
|
if (keywordHTMLStart>=0) {
|
|
int keywordHTMLLength = pos-keywordHTMLStart;
|
|
if (isLast && isAlnum) keywordHTMLLength += 1;
|
|
if ((keywordHTMLprevChar=="<" || (keywordHTMLprevChar=="/" && keywordHTMLprevPrevChar=="<")) && keywordStringHTML != "script" && keywordStringHTML != "style") {
|
|
HW->htmlwordsIterator = HW->htmlwords.find(keywordStringHTML.toLower().toStdString());
|
|
if (HW->htmlwordsIterator != HW->htmlwords.end()) {
|
|
QTextCharFormat format = HW->htmlwordsIterator->second;
|
|
highlightString(keywordHTMLStart, keywordHTMLLength, format);
|
|
} else {
|
|
highlightString(keywordHTMLStart, keywordHTMLLength, HW->tagNameFormat);
|
|
}
|
|
if (keywordHTMLprevChar == "/") {
|
|
addSpecialWord(keywordHTMLprevChar+keywordStringHTML, keywordHTMLStart);
|
|
// close tag chain
|
|
if (tagChainHTML.size() > 0) {
|
|
QStringList tagChainList = tagChainHTML.split(",");
|
|
QString lastTag = tagChainList.last();
|
|
if (lastTag.toLower() == keywordStringHTML.toLower()) {
|
|
tagChainList.removeLast();
|
|
tagChainEndsHTML.append(keywordHTMLStart+keywordStringHTML.size());
|
|
QString tagChainN = "";
|
|
for (int i=0; i<tagChainList.size(); i++) {
|
|
if (tagChainN.size() > 0) tagChainN += ",";
|
|
tagChainN += tagChainList.at(i);
|
|
}
|
|
if (tagChainN.size() > 0) {
|
|
tagChainStartsHTML.append(keywordHTMLStart+keywordStringHTML.size()+1);
|
|
tagChainsHTML.append(tagChainN);
|
|
}
|
|
tagChainHTML = tagChainN;
|
|
}
|
|
}
|
|
} else {
|
|
addSpecialWord(keywordStringHTML, keywordHTMLStart);
|
|
// open tag chain
|
|
if (tagChainStartsHTML.size() > tagChainEndsHTML.size() && tagChainHTML.size() > 0 && keywordHTMLStart > 0) {
|
|
tagChainEndsHTML.append(keywordHTMLStart-1);
|
|
}
|
|
if (tagChainHTML.size() > 0) tagChainHTML += ",";
|
|
tagChainHTML += keywordStringHTML.toLower();
|
|
tagChainStartsHTML.append(keywordHTMLStart);
|
|
tagChainsHTML.append(tagChainHTML);
|
|
}
|
|
}
|
|
keywordHTMLprevPrevChar = c;
|
|
keywordHTMLprevChar = c;
|
|
}
|
|
|
|
// close open short tag
|
|
if (tagChainStartsHTML.size() > tagChainEndsHTML.size() && tagChainHTML.size() > 0 && c.toLatin1() == '>' && tagChanged) {
|
|
QStringList tagChainList = tagChainHTML.split(",");
|
|
bool doClose = false;
|
|
if (prevC.toLatin1() == '/') doClose = true;
|
|
if (!doClose) {
|
|
QString lastTag = tagChainList.last();
|
|
HW->htmlshortsIterator = HW->htmlshorts.find(lastTag.toLower().toStdString());
|
|
if (HW->htmlshortsIterator != HW->htmlshorts.end()) {
|
|
doClose = true;
|
|
}
|
|
}
|
|
if (doClose) {
|
|
tagChainList.removeLast();
|
|
tagChainEndsHTML.append(pos);
|
|
QString tagChainN = "";
|
|
for (int y=0; y<tagChainList.size(); y++) {
|
|
if (tagChainN.size() > 0) tagChainN += ",";
|
|
tagChainN += tagChainList.at(y);
|
|
}
|
|
if (tagChainN.size() > 0) {
|
|
tagChainStartsHTML.append(pos+1);
|
|
tagChainsHTML.append(tagChainN);
|
|
}
|
|
tagChainHTML = tagChainN;
|
|
}
|
|
}
|
|
|
|
// tabs and spaces
|
|
if (stringSQOpenedHTML < 0 && stringDQOpenedHTML < 0 && commentHTMLOpened < 0 && keywordHTMLOpened < 0) {
|
|
if (highlightTabs && c.toLatin1() == '\t') {
|
|
highlightChar(pos, HW->tabFormat);
|
|
} else if (highlightSpaces && c.toLatin1() == ' ') {
|
|
highlightChar(pos, HW->spaceFormat);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Highlight::parseCSS(const QChar & c, int pos, bool isAlpha, bool isAlnum, bool isWSpace, bool isLast, int & keywordCSSStartPrev, int & keywordCSSLengthPrev, bool & cssValuePart)
|
|
{
|
|
if (mode != MODE_CSS) return;
|
|
// css string (single quote)
|
|
bool stringSQchangedCSS = detectStringSQCSS(c, pos);
|
|
if ((stringSQOpenedCSS>=0 && state == STATE_STRING_SQ_CSS) || stringSQchangedCSS) {
|
|
highlightChar(pos, HW->stringFormat);
|
|
}
|
|
|
|
// css string (double quote)
|
|
bool stringDQchangedCSS = detectStringDQCSS(c, pos);
|
|
if ((stringDQOpenedCSS>=0 && state == STATE_STRING_DQ_CSS)|| stringDQchangedCSS) {
|
|
highlightChar(pos, HW->stringFormat);
|
|
}
|
|
|
|
// comments (multi-line)
|
|
bool commentsMLchangedCSS = detectMLCommentCSS(c, pos);
|
|
if ((commentMLOpenedCSS>=0 && state == STATE_COMMENT_ML_CSS)|| commentsMLchangedCSS) {
|
|
highlightChar(pos, HW->multiLineCommentFormat);
|
|
if (commentMLOpenedCSS>=0 && state == STATE_COMMENT_ML_CSS && commentsMLchangedCSS && pos>0) {
|
|
highlightChar(pos-1, HW->multiLineCommentFormat);
|
|
}
|
|
}
|
|
|
|
// keywords & selectors && functions
|
|
int keywordCSSStart = detectKeywordCSS(c, pos, isAlpha, isAlnum, isLast);
|
|
if (keywordCSSStart>=0) {
|
|
if (keywordCSSprevChar == "@" && keywordStringCSS == "media") {
|
|
cssMediaScope = true;
|
|
if (mediaNameCSS.size() == 0 && mediaScopeCSS < 0) {
|
|
expectedMediaNameCSS = keywordStringCSS;
|
|
expectedMediaParsCSS = -1;
|
|
}
|
|
}
|
|
int keywordCSSLength = pos-keywordCSSStart;
|
|
if (isLast && (isAlnum || c.toLatin1() == '-')) keywordCSSLength += 1;
|
|
if ((keywordCSSprevChar == "@" || keywordCSSprevChar == "!") && keywordCSSStart>0) {
|
|
keywordCSSStart -= 1;
|
|
keywordCSSLength += 1;
|
|
}
|
|
if (keywordCSSprevChar != "#" && keywordCSSprevChar != "." && keywordCSSprevPrevChar != "&") {
|
|
bool kFound = false;
|
|
if (keywordCSSprevChar != "$" && keywordCSSprevChar != "%") {
|
|
// css keywords
|
|
if (!isBigFile) {
|
|
HW->csswordsIterator = HW->csswords.find(keywordStringCSS.toLower().toStdString());
|
|
if (HW->csswordsIterator != HW->csswords.end()) {
|
|
QTextCharFormat format = HW->csswordsIterator->second;
|
|
highlightString(keywordCSSStart, keywordCSSLength, format);
|
|
keywordCSSStart = -1;
|
|
kFound = true;
|
|
}
|
|
}
|
|
if (!kFound && cssValuePart) {
|
|
// css selectors
|
|
HW->htmlwordsIterator = HW->htmlwords.find(keywordStringCSS.toLower().toStdString());
|
|
if (HW->htmlwordsIterator != HW->htmlwords.end()) {
|
|
highlightString(keywordCSSStart, keywordCSSLength, HW->selectorTagFormat);
|
|
kFound = true;
|
|
}
|
|
}
|
|
}
|
|
if (!kFound && !isBigFile) {
|
|
if (keywordCSSprevChar == "$" && keywordCSSStart > 0) {
|
|
highlightString(keywordCSSStart-1, keywordCSSLength+1, HW->variableFormat);
|
|
} else if (keywordCSSprevChar == "%" && keywordCSSStart > 0) {
|
|
highlightString(keywordCSSStart-1, keywordCSSLength+1, HW->knownVariableFormat);
|
|
} else if (bracesCSS > 0 && cssValuePart) {
|
|
// css properties
|
|
highlightString(keywordCSSStart, keywordCSSLength, HW->propertyFormat);
|
|
}
|
|
}
|
|
} else if ((keywordCSSprevChar == "#" || keywordCSSprevChar == ".") && parensCSS == 0) {
|
|
// css id & class selectors
|
|
if (keywordCSSStart > 0) {
|
|
keywordCSSStart -= 1;
|
|
keywordCSSLength += 1;
|
|
}
|
|
QString cssName = keywordCSSprevChar + keywordStringCSS;
|
|
cssNamesIterator = cssNames.find(cssName.toStdString());
|
|
if (cssNamesIterator != cssNames.end()) {
|
|
highlightString(keywordCSSStart, keywordCSSLength, HW->selectorFormat);
|
|
} else if (!isColorKeyword) {
|
|
if (cssNamesChain.size() > 0) cssNamesChain += ",";
|
|
cssNamesChain += cssName;
|
|
highlightString(keywordCSSStart, keywordCSSLength, HW->selectorTagFormat);
|
|
}
|
|
}
|
|
if (keywordCSSprevChar == "#" && !cssValuePart && isColorKeyword && !isBigFile && (keywordStringCSS.length() == 3 || keywordStringCSS.length() == 6 || keywordStringCSS.length() == 8) && QColor::isValidColor(keywordCSSprevChar+keywordStringCSS)) {
|
|
// colors
|
|
if (keywordCSSStart > 0 && parensCSS == 0) {
|
|
keywordCSSStart += 1;
|
|
keywordCSSLength -= 1;
|
|
}
|
|
HW->colorFormat.setUnderlineColor(QColor(keywordCSSprevChar+keywordStringCSS));
|
|
highlightString(keywordCSSStart, keywordCSSLength, HW->colorFormat);
|
|
}
|
|
keywordCSSprevChar = c;
|
|
keywordCSSprevPrevChar = c;
|
|
keywordCSSStartPrev = keywordCSSStart;
|
|
keywordCSSLengthPrev = keywordCSSLength;
|
|
}
|
|
if (keywordCSSStartPrev>=0 && keywordCSSLengthPrev>0) {
|
|
// css functions
|
|
if (c.toLatin1() == '(') {
|
|
highlightString(keywordCSSStartPrev, keywordCSSLengthPrev, HW->functionFormat);
|
|
keywordCSSStartPrev = -1;
|
|
keywordCSSLengthPrev = -1;
|
|
} else if (!isWSpace) {
|
|
keywordCSSStartPrev = -1;
|
|
keywordCSSLengthPrev = -1;
|
|
}
|
|
}
|
|
|
|
// css curly brackets
|
|
if (stringSQOpenedCSS < 0 && stringDQOpenedCSS < 0 && commentMLOpenedCSS < 0 && keywordCSSOpened < 0 && c.toLatin1() == '{') {
|
|
bracesCSS++;
|
|
cssValuePart = true;
|
|
if (expectedMediaNameCSS.size() > 0 && expectedMediaParsCSS < 0) {
|
|
if (mediaStartsCSS.size() > mediaEndsCSS.size()) mediaEndsCSS.append(pos);
|
|
mediaNameCSS = expectedMediaNameCSS;
|
|
mediaScopeCSS = bracesCSS - 1;
|
|
mediaNamesCSS.append(mediaNameCSS);
|
|
mediaStartsCSS.append(pos+1);
|
|
expectedMediaNameCSS = "";
|
|
expectedMediaParsCSS = -1;
|
|
}
|
|
} else if (stringSQOpenedCSS < 0 && stringDQOpenedCSS < 0 && commentMLOpenedCSS < 0 && keywordCSSOpened < 0 && c.toLatin1() == '}') {
|
|
bracesCSS--;
|
|
if (bracesCSS < 0) bracesCSS = 0;
|
|
if (bracesCSS == 0 && cssMediaScope) {
|
|
cssMediaScope = false;
|
|
}
|
|
if (bracesCSS == 0 && !cssValuePart) {
|
|
cssValuePart = true;
|
|
}
|
|
if (mediaScopeCSS >=0 && mediaScopeCSS == bracesCSS) {
|
|
mediaEndsCSS.append(pos);
|
|
mediaNameCSS = "";
|
|
mediaScopeCSS = -1;
|
|
expectedMediaNameCSS = "";
|
|
expectedMediaParsCSS = -1;
|
|
}
|
|
}
|
|
if (stringSQOpenedCSS < 0 && stringDQOpenedCSS < 0 && commentMLOpenedCSS < 0 && keywordCSSOpened < 0 && c.toLatin1() == ':') {
|
|
cssValuePart = false;
|
|
} else if (stringSQOpenedCSS < 0 && stringDQOpenedCSS < 0 && commentMLOpenedCSS < 0 && keywordCSSOpened < 0 && c.toLatin1() == ';') {
|
|
cssValuePart = true;
|
|
}
|
|
|
|
// css parentheses
|
|
if (stringSQOpenedCSS < 0 && stringDQOpenedCSS < 0 && commentMLOpenedCSS < 0 && keywordCSSOpened < 0 && c.toLatin1() == '(') {
|
|
parensCSS++;
|
|
if (expectedMediaNameCSS.size() > 0 && expectedMediaNameCSS == "media") {
|
|
expectedMediaParsCSS = parensCSS-1;
|
|
expectedMediaNameCSS = "";
|
|
}
|
|
} else if (stringSQOpenedCSS < 0 && stringDQOpenedCSS < 0 && commentMLOpenedCSS < 0 && keywordCSSOpened < 0 && c.toLatin1() == ')') {
|
|
parensCSS--;
|
|
if (parensCSS < 0) parensCSS = 0;
|
|
if (expectedMediaParsCSS >= 0 && expectedMediaParsCSS == parensCSS) {
|
|
expectedMediaParsCSS = -1;
|
|
}
|
|
}
|
|
|
|
// expected media
|
|
if (expectedMediaParsCSS >= 0 && c.toLatin1() != '(' && c.toLatin1() != ')') {
|
|
expectedMediaNameCSS += c;
|
|
}
|
|
// unexpected media
|
|
if (expectedMediaNameCSS.size() > 0 && (c.toLatin1() == ';' || c.toLatin1() == '{')) {
|
|
expectedMediaNameCSS = "";
|
|
expectedMediaParsCSS = -1;
|
|
}
|
|
|
|
// saving special chars data
|
|
if (stringSQOpenedCSS < 0 && stringDQOpenedCSS < 0 && commentMLOpenedCSS < 0 && keywordCSSOpened < 0 && (c.toLatin1() == '{' || c.toLatin1() == '}' || c.toLatin1() == '(' || c.toLatin1() == ')' || c.toLatin1() == '[' || c.toLatin1() == ']')) {
|
|
addSpecialChar(c, pos);
|
|
}
|
|
|
|
// tabs, spaces, semicolons, commas
|
|
if (stringSQOpenedCSS < 0 && stringDQOpenedCSS < 0 && commentMLOpenedCSS < 0 && keywordCSSOpened < 0) {
|
|
if (highlightTabs && c.toLatin1() == '\t') {
|
|
highlightChar(pos, HW->tabFormat);
|
|
} else if (highlightSpaces && c.toLatin1() == ' ') {
|
|
highlightChar(pos, HW->spaceFormat);
|
|
}
|
|
if (!isBigFile && (c.toLatin1() == ';' || c.toLatin1() == ',' || c.toLatin1() == '{' || c.toLatin1() == '}' || c.toLatin1() == '(' || c.toLatin1() == ')' || c.toLatin1() == '[' || c.toLatin1() == ']')) {
|
|
highlightChar(pos, HW->punctuationFormat);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Highlight::parseJS(const QChar & c, int pos, bool isAlpha, bool isAlnum, bool isWSpace, bool isLast, int & keywordJSStartPrev, int & keywordJSLengthPrev)
|
|
{
|
|
if (mode != MODE_JS) return;
|
|
|
|
// js string (single quote)
|
|
bool stringSQchangedJS = detectStringSQJS(c, pos);
|
|
if ((stringSQOpenedJS>=0 && state == STATE_STRING_SQ_JS) || stringSQchangedJS) {
|
|
highlightChar(pos, HW->stringFormat);
|
|
}
|
|
|
|
// js string (double quote)
|
|
bool stringDQchangedJS = detectStringDQJS(c, pos);
|
|
if ((stringDQOpenedJS>=0 && state == STATE_STRING_DQ_JS) || stringDQchangedJS) {
|
|
highlightChar(pos, HW->stringFormat);
|
|
}
|
|
|
|
// js template
|
|
bool exprChangedJS = detectExpressionJS(c, pos);
|
|
if ((exprOpenedJS>=0 && state == STATE_EXPRESSION_JS) || exprChangedJS) {
|
|
highlightChar(pos, HW->knownFormat);
|
|
}
|
|
|
|
// js template expression
|
|
if (exprOpenedJS >= 0 && c.toLatin1() == '$' && stringEscVariableJS.size()%2 == 0) {
|
|
keywordJSScopedOpened = pos;
|
|
keywordJSScoped = false;
|
|
} else if (exprOpenedJS >= 0 && keywordJSScopedOpened >= 0 && c.toLatin1() == '{' && !keywordJSScoped) {
|
|
keywordJSScoped = true;
|
|
highlightString(keywordJSScopedOpened, pos-keywordJSScopedOpened, HW->expressionFormat);
|
|
} else if (exprOpenedJS >= 0 && keywordJSScopedOpened >= 0 && !isWSpace && !keywordJSScoped) {
|
|
keywordJSScopedOpened = -1;
|
|
} else if (exprOpenedJS >= 0 && keywordJSScopedOpened >= 0 && c.toLatin1() == '}' && keywordJSScoped) {
|
|
keywordJSScopedOpened = -1;
|
|
keywordJSScoped = false;
|
|
highlightChar(pos, HW->expressionFormat);
|
|
}
|
|
if (exprOpenedJS >= 0 && keywordJSScopedOpened < 0 && c.toLatin1() == '\\') {
|
|
stringEscVariableJS += c;
|
|
} else if (c.toLatin1() != '$') {
|
|
if (c.toLatin1() == '<') prevStringEscVariableJS = stringEscVariableJS;
|
|
stringEscVariableJS = "";
|
|
}
|
|
if (keywordJSScoped) {
|
|
highlightChar(pos, HW->expressionFormat);
|
|
}
|
|
|
|
// comments (single-line)
|
|
bool commentsSLchangedJS = detectSLCommentJS(c, pos);
|
|
if (commentSLOpenedJS>=0 || commentsSLchangedJS) {
|
|
highlightChar(pos, HW->singleLineCommentFormat);
|
|
if (commentSLOpenedJS>=0 && commentsSLchangedJS && pos>0) {
|
|
highlightChar(pos-1, HW->singleLineCommentFormat);
|
|
}
|
|
}
|
|
|
|
// js regexp
|
|
bool regexpchangedJS = detectRegexpJS(c, pos, isWSpace, isAlnum);
|
|
if ((regexpOpenedJS>=0 && state == STATE_REGEXP_JS)|| regexpchangedJS) {
|
|
highlightChar(pos, HW->stringFormat);
|
|
}
|
|
|
|
// comments (multi-line)
|
|
if (!(regexpOpenedJS<0 && regexpchangedJS)) {
|
|
bool commentsMLchangedJS = detectMLCommentJS(c, pos);
|
|
if ((commentMLOpenedJS>=0 && state == STATE_COMMENT_ML_JS)|| commentsMLchangedJS) {
|
|
highlightChar(pos, HW->multiLineCommentFormat);
|
|
if (commentMLOpenedJS>=0 && state == STATE_COMMENT_ML_JS && commentsMLchangedJS && pos>0) {
|
|
highlightChar(pos-1, HW->multiLineCommentFormat);
|
|
}
|
|
}
|
|
} else {
|
|
commentJSStringML = "";
|
|
}
|
|
|
|
// keywords & functions
|
|
int keywordJSStart = detectKeywordJS(c, pos, isAlpha, isAlnum, isLast);
|
|
bool isExpectJSVarChar = (c.toLatin1() == ')' || c.toLatin1() == '[' || c.toLatin1() == ']' || c.toLatin1() == '}' || c.toLatin1() == ';' || c.toLatin1() == '=' || c.toLatin1() == ',' || c.toLatin1() == '+' || c.toLatin1() == '-' || c.toLatin1() == '*' || c.toLatin1() == '/' || c.toLatin1() == '~' || c.toLatin1() == '%' || c.toLatin1() == '&' || c.toLatin1() == '?' || c.toLatin1() == ':' || c.toLatin1() == '<' || c.toLatin1() == '>' || c.toLatin1() == '|');
|
|
if (keywordJSStart>=0) {
|
|
int keywordJSLength = pos-keywordJSStart;
|
|
if (isLast && (isAlnum || c.toLatin1() == '$')) keywordJSLength += 1;
|
|
bool known = false;
|
|
bool isKeyword = false;
|
|
if (keywordJSprevChar != "$" && (keywordJSprevChar != "." || keywordStringJS == "prototype") && keywordStringJS.size()>0) {
|
|
// js keywords
|
|
HW->jswordsCSIterator = HW->jswordsCS.find(keywordStringJS.toStdString());
|
|
if (HW->jswordsCSIterator != HW->jswordsCS.end()) {
|
|
QTextCharFormat format = HW->jswordsCSIterator->second;
|
|
if (keywordStringJS == "prototype" && keywordJSprevChar == ".") {
|
|
highlightString(keywordJSStart, keywordJSLength, HW->keywordFormat);
|
|
} else {
|
|
highlightString(keywordJSStart, keywordJSLength, format);
|
|
}
|
|
keywordJSStart = -1;
|
|
known = true;
|
|
isKeyword = true;
|
|
}
|
|
if (!known && jsExtMode == EXTENSION_DART) {
|
|
HW->jsExtDartWordsCSIterator = HW->jsExtDartWordsCS.find(keywordStringJS.toStdString());
|
|
if (HW->jsExtDartWordsCSIterator != HW->jsExtDartWordsCS.end()) {
|
|
QTextCharFormat format = HW->jsExtDartWordsCSIterator->second;
|
|
highlightString(keywordJSStart, keywordJSLength, format);
|
|
keywordJSStart = -1;
|
|
known = true;
|
|
isKeyword = true;
|
|
}
|
|
}
|
|
if (!known && c.toLatin1() != ':' && c.toLatin1() != '.' && !isBigFile) {
|
|
jsNamesIterator = jsNames.find(keywordStringJS.toStdString());
|
|
if (jsNamesIterator != jsNames.end()) {
|
|
highlightString(keywordJSStart, keywordJSLength, HW->variableFormat);
|
|
known = true;
|
|
}
|
|
}
|
|
}
|
|
if (!known && !isBigFile) {
|
|
if ((keywordJSprevString == "var" || keywordJSprevString == "let" || keywordJSprevString == "const") && keywordJSprevStringPrevChar != ".") {
|
|
if (varsChainJS.size() > 0) varsChainJS += ",";
|
|
varsChainJS += keywordStringJS;
|
|
jsNames[keywordStringJS.toStdString()] = keywordStringJS.toStdString();
|
|
highlightString(keywordJSStart, keywordJSLength, HW->variableFormat);
|
|
} else if (keywordJSprevChar != "." && c.toLatin1() == '.') {
|
|
highlightString(keywordJSStart, keywordJSLength, HW->classFormat);
|
|
} else if (keywordJSprevChar == ".") {
|
|
highlightString(keywordJSStart, keywordJSLength, HW->propertyFormat);
|
|
} else if (keywordJSprevChar != "." && c.toLatin1() == ':') {
|
|
highlightString(keywordJSStart, keywordJSLength, HW->propertyFormat);
|
|
} else if (keywordJSprevChar == "@") {
|
|
highlightString(keywordJSStart, keywordJSLength, HW->punctuationFormat);
|
|
} else if (keywordJSprevChar == "<" && c.toLatin1() == '>') {
|
|
highlightString(keywordJSStart, keywordJSLength, HW->classFormat);
|
|
} else if (keywordJSprevString == "class" || keywordJSprevString == "extends" || keywordJSprevString == "with") {
|
|
highlightString(keywordJSStart, keywordJSLength, HW->classFormat);
|
|
} else if (expectedFuncNameJS.size() > 0 || expectedFuncParsJS >= 0) { // add arg if var is unknown
|
|
expectedFuncArgsJS.append(keywordStringJS);
|
|
highlightString(keywordJSStart, keywordJSLength, HW->variableFormat);
|
|
} else if (isExpectJSVarChar || (isLast && (isAlnum || c.toLatin1() == '$'))) {
|
|
highlightString(keywordJSStart, keywordJSLength, HW->variableFormat);
|
|
} else if (!expectJSVar && (c.isSpace() || isLast)) {
|
|
expectJSVar = true;
|
|
}
|
|
}
|
|
//if (keywordJSStartPrev>=0 && keywordJSLengthPrev>0) {
|
|
if (prevIsKeyword && !isBigFile) {
|
|
highlightString(keywordJSStartPrev, keywordJSLengthPrev, HW->classFormat);
|
|
expectVarInit = true;
|
|
}
|
|
if (keywordStringJS.size()>0 && !isBigFile) {
|
|
// class scope
|
|
if (keywordStringJS.size() > 0 && (((keywordStringJS.toLower() == "class" || keywordStringJS.toLower() == "interface") && expectedClsNameJS.size() == 0) || expectedClsNameJS.toLower() == "class" || expectedClsNameJS.toLower() == "interface")) {
|
|
expectedClsNameJS = keywordStringJS;
|
|
}
|
|
// function scope
|
|
if (expectedFuncNameJS.size() == 0 && keywordStringJS.size() > 0 && keywordStringJS != "function" && !isKeyword) {
|
|
expectedFuncNameJS = "";
|
|
expectedFuncVarJS = keywordStringJS;
|
|
expectedFuncParsJS = -1;
|
|
expectedFuncArgsJS.clear();
|
|
} else if (expectedFuncNameJS.size() == 0 && expectedFuncVarJS.size() > 0 && keywordStringJS == "function" && expectedFuncVarJS.indexOf("=") > 0) {
|
|
QStringList expectedFuncNameJSList = expectedFuncVarJS.split("=");
|
|
if (expectedFuncNameJSList.size() == 2 && expectedFuncNameJSList.at(1) == "function") {
|
|
expectedFuncNameJS = expectedFuncNameJSList.at(0);
|
|
expectedFuncVarJS = "";
|
|
expectedFuncParsJS = parensJS;
|
|
} else {
|
|
expectedFuncNameJS = "";
|
|
expectedFuncVarJS = "";
|
|
expectedFuncParsJS = -1;
|
|
}
|
|
expectedFuncArgsJS.clear();
|
|
} else if (keywordStringJS.size() > 0 && (keywordStringJS == "function" || expectedFuncNameJS == "function")) {
|
|
expectedFuncNameJS = keywordStringJS;
|
|
expectedFuncVarJS = "";
|
|
expectedFuncParsJS = parensJS;
|
|
expectedFuncArgsJS.clear();
|
|
} else {
|
|
expectedFuncVarJS = "";
|
|
}
|
|
}
|
|
if (keywordJSprevChar != "." && keywordJSprevChar != "@") {
|
|
prevIsKeyword = true;
|
|
}
|
|
keywordJSprevString = keywordStringJS;
|
|
keywordJSprevStringPrevChar = keywordJSprevChar;
|
|
keywordJSprevChar = c;
|
|
keywordJSStartPrev = keywordJSStart;
|
|
keywordJSLengthPrev = keywordJSLength;
|
|
}
|
|
if (keywordJSStartPrev>=0 && keywordJSLengthPrev>0) {
|
|
// js functions, variables, classes
|
|
if (c.toLatin1() == '(') {
|
|
highlightString(keywordJSStartPrev, keywordJSLengthPrev, HW->functionFormat);
|
|
} else if (expectJSVar && (isExpectJSVarChar || (isLast && isWSpace))) {
|
|
highlightString(keywordJSStartPrev, keywordJSLengthPrev, HW->variableFormat);
|
|
}
|
|
if (!isWSpace) {
|
|
if (!isAlnum && c.toLatin1() != '$') {
|
|
keywordJSStartPrev = -1;
|
|
keywordJSLengthPrev = -1;
|
|
}
|
|
expectJSVar = false;
|
|
}
|
|
}
|
|
if (expectVarInit) {
|
|
if (c.toLatin1() == '=' && keywordStringJS.size() > 0 && keywordJSprevChar != ".") {
|
|
if (varsChainJS.size() > 0) varsChainJS += ",";
|
|
varsChainJS += keywordStringJS;
|
|
jsNames[keywordStringJS.toStdString()] = keywordStringJS.toStdString();
|
|
}
|
|
if (!isWSpace) {
|
|
expectVarInit = false;
|
|
}
|
|
}
|
|
if (!isWSpace && !isAlnum && c.toLatin1() != '$') {
|
|
prevIsKeyword = false;
|
|
}
|
|
|
|
// js curly brackets
|
|
if (stringSQOpenedJS < 0 && stringDQOpenedJS < 0 && commentSLOpenedJS < 0 && commentMLOpenedJS < 0 && regexpOpenedJS < 0 && keywordJSOpened < 0 && c.toLatin1() == '{') {
|
|
bracesJS++;
|
|
// open class scope
|
|
if (expectedClsNameJS.size() > 0) {
|
|
QString cClsNameJS = clsNameJS;
|
|
int cClsScopeJS = clsScopeJS;
|
|
if (clsScopeJS < 0) cClsNameJS = "";
|
|
if (expectedClsNameJS == "class" || expectedClsNameJS == "implements" || expectedClsNameJS == "extends") expectedClsNameJS = "anonymous class";
|
|
if (clsStartsJS.size() > clsEndsJS.size()) clsEndsJS.append(pos);
|
|
clsNameJS = expectedClsNameJS;
|
|
clsScopeJS = bracesJS-1;
|
|
clsNamesJS.append(clsNameJS);
|
|
clsStartsJS.append(pos+1);
|
|
if (clsChainJS.size() > 0) clsChainJS += ",";
|
|
clsChainJS += cClsNameJS;
|
|
clsScopeChainJS.append(cClsScopeJS);
|
|
expectedClsNameJS = "";
|
|
expectedFuncArgsJS.clear();
|
|
clsOpensJS.append(clsOpenJS);
|
|
clsOpenJS = true;
|
|
}
|
|
// open function scope
|
|
if (expectedFuncNameJS.size() > 0 && expectedFuncParsJS == parensJS) {
|
|
QString cFuncNameJS = funcNameJS;
|
|
int cFuncScopeJS = funcScopeJS;
|
|
if (funcScopeJS < 0) cFuncNameJS = "";
|
|
if (funcStartsJS.size() > funcEndsJS.size()) funcEndsJS.append(pos);
|
|
funcNameJS = expectedFuncNameJS;
|
|
funcScopeJS = bracesJS-1;
|
|
funcNamesJS.append(funcNameJS);
|
|
funcStartsJS.append(pos+1);
|
|
expectedFuncNameJS = "";
|
|
expectedFuncParsJS = -1;
|
|
if (funcChainJS.size() > 0) funcChainJS += ",";
|
|
funcChainJS += cFuncNameJS;
|
|
funcScopeChainJS.append(cFuncScopeJS);
|
|
if (expectedFuncArgsJS.size() > 0) {
|
|
for (int i=0; i<expectedFuncArgsJS.size(); i++) {
|
|
if (varsChainJS.size() > 0) varsChainJS += ",";
|
|
varsChainJS += expectedFuncArgsJS.at(i);
|
|
}
|
|
}
|
|
expectedFuncArgsJS.clear();
|
|
}
|
|
} else if (stringSQOpenedJS < 0 && stringDQOpenedJS < 0 && commentSLOpenedJS < 0 && commentMLOpenedJS < 0 && regexpOpenedJS < 0 && keywordJSOpened < 0 && c.toLatin1() == '}') {
|
|
bracesJS--;
|
|
if (bracesJS < 0) bracesJS = 0;
|
|
// close class scope
|
|
if (clsNameJS.size() > 0 && clsScopeJS >= 0 && clsScopeJS == bracesJS) {
|
|
clsNameJS = "";
|
|
clsScopeJS = -1;
|
|
clsEndsJS.append(pos);
|
|
expectedClsNameJS = "";
|
|
// set parent cls
|
|
int parentClsScopeJS = -1;
|
|
QString parentClsJS = "", parentClsChainJS = "";
|
|
if (!clsScopeChainJS.isEmpty()) {
|
|
parentClsScopeJS = clsScopeChainJS.last();
|
|
clsScopeChainJS.removeLast();
|
|
QStringList clsChainListJS = clsChainJS.split(",");
|
|
parentClsJS = clsChainListJS.last();
|
|
for (int i=0; i<clsChainListJS.size()-1; i++) {
|
|
if (parentClsChainJS.size() > 0) parentClsChainJS += ",";
|
|
parentClsChainJS += clsChainListJS.at(i);
|
|
}
|
|
if (parentClsScopeJS >= 0 && parentClsJS.size() > 0) {
|
|
clsNameJS = parentClsJS;
|
|
clsChainJS = parentClsChainJS;
|
|
clsNamesJS.append(clsNameJS);
|
|
clsStartsJS.append(pos+1);
|
|
clsScopeJS = parentClsScopeJS;
|
|
}
|
|
}
|
|
if (!clsOpensJS.isEmpty()) {
|
|
clsOpenJS = clsOpensJS.last();
|
|
clsOpensJS.removeLast();
|
|
} else {
|
|
clsOpenJS = false;
|
|
}
|
|
}
|
|
// close function scope
|
|
if (funcNameJS.size() > 0 && funcScopeJS >= 0 && funcScopeJS == bracesJS) {
|
|
funcNameJS = "";
|
|
funcScopeJS = -1;
|
|
funcEndsJS.append(pos);
|
|
expectedFuncNameJS = "";
|
|
expectedFuncParsJS = -1;
|
|
expectedFuncArgsJS.clear();
|
|
// set parent function
|
|
int parentFuncScopeJS = -1;
|
|
QString parentFuncJS = "", parentFuncChainJS = "";
|
|
if (!funcScopeChainJS.isEmpty()) {
|
|
parentFuncScopeJS = funcScopeChainJS.last();
|
|
funcScopeChainJS.removeLast();
|
|
QStringList funcChainListJS = funcChainJS.split(",");
|
|
parentFuncJS = funcChainListJS.last();
|
|
for (int i=0; i<funcChainListJS.size()-1; i++) {
|
|
if (parentFuncChainJS.size() > 0) parentFuncChainJS += ",";
|
|
parentFuncChainJS += funcChainListJS.at(i);
|
|
}
|
|
if (parentFuncScopeJS >= 0 && parentFuncJS.size() > 0) {
|
|
funcNameJS = parentFuncJS;
|
|
funcChainJS = parentFuncChainJS;
|
|
funcNamesJS.append(funcNameJS);
|
|
funcStartsJS.append(pos+1);
|
|
funcScopeJS = parentFuncScopeJS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (expectedFuncNameJS.size() > 0 && expectedFuncNameJS == "function" && c.toLatin1() == '(' && expectedFuncParsJS == parensJS) {
|
|
expectedFuncNameJS = "anonymous function";
|
|
}
|
|
|
|
// unexpected class scope
|
|
if (expectedClsNameJS.size() > 0 && expectedClsNameJS.toLower() == "class" && c.toLatin1() == '(') {
|
|
expectedClsNameJS = "anonymous class";
|
|
} else if (expectedClsNameJS.size() > 0 && c.toLatin1() == ';') {
|
|
expectedClsNameJS = "";
|
|
}
|
|
// unexpected function scope
|
|
if (expectedFuncNameJS.size() > 0 && expectedFuncNameJS != "function" && (c.toLatin1() == ';' || c.toLatin1() == ')' || c.toLatin1() == '}' || c.toLatin1() == ']' || c.toLatin1() == ',' || c.toLatin1() == ':' || c.toLatin1() == '=' || c.toLatin1() == '+' || c.toLatin1() == '-' || c.toLatin1() == '*' || c.toLatin1() == '/' || c.toLatin1() == '%' || c.toLatin1() == '&' || c.toLatin1() == '|' || c.toLatin1() == '?') && expectedFuncParsJS == parensJS) {
|
|
expectedFuncNameJS = "";
|
|
expectedFuncParsJS = -1;
|
|
expectedFuncArgsJS.clear();
|
|
}
|
|
if (keywordJSStart < 0 && expectedFuncVarJS.size() > 0 && expectedFuncParsJS < 0 && !isWSpace && (isAlnum || c.toLatin1() == '=')) {
|
|
expectedFuncVarJS += c;
|
|
} else if (expectedFuncVarJS.size() > 0 && expectedFuncParsJS < 0 && expectedFuncVarJS.indexOf("=") < 0 && c.toLatin1() == '(') {
|
|
expectedFuncNameJS = expectedFuncVarJS;
|
|
expectedFuncVarJS = "";
|
|
expectedFuncParsJS = parensJS;
|
|
expectedFuncArgsJS.clear();
|
|
} else if (expectedFuncVarJS.size() > 0 && expectedFuncParsJS < 0 && !isWSpace) {
|
|
expectedFuncVarJS = "";
|
|
}
|
|
|
|
// js parentheses
|
|
if (stringSQOpenedJS < 0 && stringDQOpenedJS < 0 && commentSLOpenedJS < 0 && commentMLOpenedJS < 0 && regexpOpenedJS < 0 && keywordJSOpened < 0 && c.toLatin1() == '(') {
|
|
parensJS++;
|
|
operatorsJS[parensJS] = "";
|
|
} else if (stringSQOpenedJS < 0 && stringDQOpenedJS < 0 && commentSLOpenedJS < 0 && commentMLOpenedJS < 0 && regexpOpenedJS < 0 && keywordJSOpened < 0 && c.toLatin1() == ')') {
|
|
operatorsJS[parensJS] = "";
|
|
parensJS--;
|
|
if (parensJS < 0) parensJS = 0;
|
|
}
|
|
|
|
// saving special chars data
|
|
if (stringSQOpenedJS < 0 && stringDQOpenedJS < 0 && commentSLOpenedJS < 0 && commentMLOpenedJS < 0 && regexpOpenedJS < 0 && keywordJSOpened < 0 && (c.toLatin1() == '{' || c.toLatin1() == '}' || c.toLatin1() == '(' || c.toLatin1() == ')' || c.toLatin1() == '[' || c.toLatin1() == ']')) {
|
|
addSpecialChar(c, pos);
|
|
}
|
|
|
|
// tabs, spaces, semicolons, commas
|
|
if (stringSQOpenedJS < 0 && stringDQOpenedJS < 0 && commentSLOpenedJS < 0 && commentMLOpenedJS < 0 && regexpOpenedJS < 0 && keywordJSOpened < 0) {
|
|
if (highlightTabs && c.toLatin1() == '\t') {
|
|
highlightChar(pos, HW->tabFormat);
|
|
} else if (highlightSpaces && c.toLatin1() == ' ') {
|
|
highlightChar(pos, HW->spaceFormat);
|
|
}
|
|
if (!isBigFile && (c.toLatin1() == ';' || c.toLatin1() == ',' || c.toLatin1() == '{' || c.toLatin1() == '}' || c.toLatin1() == '(' || c.toLatin1() == ')' || c.toLatin1() == '[' || c.toLatin1() == ']' || c.toLatin1() == '@')) {
|
|
highlightChar(pos, HW->punctuationFormat);
|
|
}
|
|
}
|
|
|
|
// "and / or" operators check
|
|
if (stringSQOpenedJS < 0 && stringDQOpenedJS < 0 && commentSLOpenedJS < 0 && commentMLOpenedJS < 0 && regexpOpenedJS < 0 && keywordJSOpened < 0) {
|
|
if (expectAndSignJS && c.toLatin1() == '&') {
|
|
operatorsJSIterator = operatorsJS.find(parensJS);
|
|
if (operatorsJSIterator != operatorsJS.end() && operatorsJSIterator->second == "|") {
|
|
highlightError(pos - 1, 2);
|
|
} else {
|
|
operatorsJS[parensJS] = "&";
|
|
}
|
|
operatorsChainJS += "&";
|
|
}
|
|
if (expectOrSignJS && c.toLatin1() == '|') {
|
|
operatorsJSIterator = operatorsJS.find(parensJS);
|
|
if (operatorsJSIterator != operatorsJS.end() && operatorsJSIterator->second == "&") {
|
|
highlightError(pos - 1, 2);
|
|
} else {
|
|
operatorsJS[parensJS] = "|";
|
|
}
|
|
operatorsChainJS += "|";
|
|
}
|
|
if (c.toLatin1() == '&') expectAndSignJS = true;
|
|
else expectAndSignJS = false;
|
|
if (c.toLatin1() == '|') expectOrSignJS = true;
|
|
else expectOrSignJS = false;
|
|
if (c.toLatin1() == ';' || c.toLatin1() == ',') {
|
|
operatorsJSIterator = operatorsJS.find(parensJS);
|
|
if (operatorsJSIterator != operatorsJS.end() && operatorsJSIterator->second != "") {
|
|
operatorsJS[parensJS] = "";
|
|
operatorsChainJS += ";";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Highlight::parsePHP(const QChar & c, int pos, bool isAlpha, bool isAlnum, bool isWSpace, bool isLast, int & keywordPHPStartPrev, int & keywordPHPLengthPrev)
|
|
{
|
|
if (mode != MODE_PHP) return;
|
|
// php string (single quote)
|
|
bool stringSQchangedPHP = detectStringSQPHP(c, pos);
|
|
if ((stringSQOpenedPHP>=0 && state == STATE_STRING_SQ_PHP) || stringSQchangedPHP) {
|
|
highlightChar(pos, HW->stringFormat);
|
|
}
|
|
|
|
// php string (double quote)
|
|
bool stringDQchangedPHP = detectStringDQPHP(c, pos);
|
|
if ((stringDQOpenedPHP>=0 && state == STATE_STRING_DQ_PHP)|| stringDQchangedPHP) {
|
|
highlightChar(pos, HW->stringFormat);
|
|
}
|
|
|
|
// php shell expression
|
|
bool exprChangedPHP = detectExpressionPHP(c, pos);
|
|
if ((exprOpenedPHP>=0 && state == STATE_EXPRESSION_PHP)|| exprChangedPHP) {
|
|
highlightChar(pos, HW->expressionFormat);
|
|
}
|
|
|
|
// comments (single-line)
|
|
bool commentsSLchangedPHP = detectSLCommentPHP(c, pos);
|
|
if (commentSLOpenedPHP>=0 || commentsSLchangedPHP) {
|
|
highlightChar(pos, HW->singleLineCommentFormat);
|
|
if (commentSLOpenedPHP>=0 && commentsSLchangedPHP && pos>0 && c.toLatin1() != '#') {
|
|
highlightChar(pos-1, HW->singleLineCommentFormat);
|
|
}
|
|
}
|
|
|
|
// comments (multi-line)
|
|
bool commentsMLchangedPHP = detectMLCommentPHP(c, pos);
|
|
if ((commentMLOpenedPHP>=0 && state == STATE_COMMENT_ML_PHP)|| commentsMLchangedPHP) {
|
|
highlightChar(pos, HW->multiLineCommentFormat);
|
|
if (commentMLOpenedPHP>=0 && state == STATE_COMMENT_ML_PHP && commentsMLchangedPHP && pos>0) {
|
|
highlightChar(pos-1, HW->multiLineCommentFormat);
|
|
}
|
|
}
|
|
|
|
// heredoc
|
|
detectStringBPHP(c, pos, isAlpha, isAlnum, isLast);
|
|
if (stringBOpened>=0 && stringBStart>=0) {
|
|
highlightString(stringBStart, pos-stringBStart+1, HW->stringFormat);
|
|
} else if (stringBOpened>=0) {
|
|
highlightChar(pos, HW->stringFormat);
|
|
}
|
|
|
|
// dq-string variables
|
|
if ((stringDQOpenedPHP >= 0 || (stringBOpened >= 0 && state == STATE_STRING_HEREDOC)) && c.toLatin1() == '{') {
|
|
keywordPHPScopedOpened = pos;
|
|
keywordPHPScoped = false;
|
|
} else if ((stringDQOpenedPHP >= 0 || (stringBOpened >= 0 && state == STATE_STRING_HEREDOC)) && keywordPHPScopedOpened >= 0 && c.toLatin1() == '$' && !keywordPHPScoped) {
|
|
keywordPHPScoped = true;
|
|
highlightString(keywordPHPScopedOpened, pos-keywordPHPScopedOpened, HW->expressionFormat);
|
|
} else if ((stringDQOpenedPHP >= 0 || (stringBOpened >= 0 && state == STATE_STRING_HEREDOC)) && keywordPHPScopedOpened >= 0 && !isWSpace && !keywordPHPScoped) {
|
|
keywordPHPScopedOpened = -1;
|
|
} else if ((stringDQOpenedPHP >= 0 || (stringBOpened >= 0 && state == STATE_STRING_HEREDOC)) && keywordPHPScopedOpened >= 0 && c.toLatin1() == '}' && keywordPHPScoped) {
|
|
keywordPHPScopedOpened = -1;
|
|
keywordPHPScoped = false;
|
|
highlightChar(pos, HW->expressionFormat);
|
|
}
|
|
bool forceDetectKeyword = false;
|
|
if ((stringDQOpenedPHP >= 0 || (stringBOpened >= 0 && state == STATE_STRING_HEREDOC)) && keywordPHPprevChar == "$" && stringEscVariablePHP.size()%2 == 0) {
|
|
forceDetectKeyword = true;
|
|
}
|
|
if ((stringDQOpenedPHP >= 0 || (stringBOpened >= 0 && state == STATE_STRING_HEREDOC)) && keywordPHPScopedOpened < 0 && c.toLatin1() == '\\') {
|
|
stringEscVariablePHP += c;
|
|
} else if (c.toLatin1() != '$') {
|
|
stringEscVariablePHP = "";
|
|
}
|
|
if (keywordPHPScoped) {
|
|
highlightChar(pos, HW->expressionFormat);
|
|
}
|
|
|
|
// keywords & variables & functions
|
|
int keywordPHPStart = detectKeywordPHP(c, pos, isAlpha, isAlnum, isLast, forceDetectKeyword);
|
|
if (keywordPHPStart>=0) {
|
|
int keywordPHPLength = pos-keywordPHPStart;
|
|
if (isLast && isAlnum) keywordPHPLength += 1;
|
|
bool isObjectContext = keywordPHPprevPrevChar == "-" && keywordPHPprevChar == ">";
|
|
if (keywordPHPprevChar != "$" && !isObjectContext && keywordPHPprevChar != ":" && keywordStringPHP.size()>1 && keywordPHPprevString.toLower() != "const" && keywordPHPprevString.toLower() != "function") {
|
|
// php keywords
|
|
HW->phpwordsIterator = HW->phpwords.find(keywordStringPHP.toLower().toStdString());
|
|
if (HW->phpwordsIterator != HW->phpwords.end()) {
|
|
QTextCharFormat format = HW->phpwordsIterator->second;
|
|
highlightString(keywordPHPStart, keywordPHPLength, format);
|
|
keywordPHPStart = -1;
|
|
} else {
|
|
HW->phpwordsCSIterator = HW->phpwordsCS.find(keywordStringPHP.toStdString());
|
|
if (HW->phpwordsCSIterator != HW->phpwordsCS.end()) {
|
|
QTextCharFormat format = HW->phpwordsCSIterator->second;
|
|
highlightString(keywordPHPStart, keywordPHPLength, format);
|
|
keywordPHPStart = -1;
|
|
}
|
|
}
|
|
if (keywordStringPHP == "global" && funcNamePHP.size() > 0) {
|
|
isGlobalPHP = true;
|
|
}
|
|
} else if ((keywordPHPprevChar == "$" || isObjectContext) && !isBigFile) {
|
|
// php variables
|
|
bool known = false;
|
|
if (keywordPHPprevChar == "$" && keywordPHPStart > 0) {
|
|
keywordPHPStart -= 1;
|
|
keywordPHPLength += 1;
|
|
QString varName = keywordPHPprevChar + keywordStringPHP;
|
|
HW->phpwordsCSIterator = HW->phpwordsCS.find(varName.toStdString());
|
|
if (HW->phpwordsCSIterator != HW->phpwordsCS.end()) {
|
|
known = true;
|
|
} else if (varName == "$this" && clsNamePHP.size() > 0) {
|
|
known = true;
|
|
} else if (expectedFuncNamePHP.size() > 0) {
|
|
expectedFuncArgsPHP.append(varName);
|
|
expectedFuncArgsPHPPositions.append(keywordPHPStart);
|
|
expectedFuncArgsPHPBlocks.append(cBlock.blockNumber());
|
|
} else if (keywordPHPprevPrevChar != ":" || keywordPHPprevStringPrevChar == "$") {
|
|
QString ns = "\\";
|
|
if (nsNamePHP.size() > 0) ns += nsNamePHP + "\\";
|
|
QString _clsName = clsNamePHP.size() > 0 ? ns + clsNamePHP : "";
|
|
QString k = _clsName + "::" + funcNamePHP;
|
|
variablesIterator = variables.find(varName.toStdString());
|
|
if (variablesIterator == variables.end()) {
|
|
variables[varName.toStdString()] = varName.toStdString();
|
|
if (varsChainPHP.size() > 0) varsChainPHP += ",";
|
|
varsChainPHP += varName;
|
|
// save to known vars
|
|
if (highlightVarsMode || firstRunMode) {
|
|
knownVars[k.toStdString()] = varsChainPHP.toStdString();
|
|
QString kk = k + "::" + varName;
|
|
knownVarsPositions[kk.toStdString()] = keywordPHPStart;
|
|
knownVarsBlocks[kk.toStdString()] = cBlock.blockNumber();
|
|
}
|
|
if (isGlobalPHP) {
|
|
if (usedVarsGlobChainPHP.size() > 0) usedVarsGlobChainPHP += ",";
|
|
usedVarsGlobChainPHP += varName;
|
|
if (highlightVarsMode || firstRunMode) {
|
|
usedVars["::"] = usedVarsGlobChainPHP.toStdString();
|
|
}
|
|
}
|
|
} else {
|
|
known = true;
|
|
usedVariablesIterator = usedVariables.find(varName.toStdString());
|
|
if (usedVariablesIterator == usedVariables.end()) {
|
|
usedVariables[varName.toStdString()] = varName.toStdString();
|
|
if (usedVarsChainPHP.size() > 0) usedVarsChainPHP += ",";
|
|
usedVarsChainPHP += varName;
|
|
}
|
|
}
|
|
if (highlightVarsMode || firstRunMode) {
|
|
usedVars[k.toStdString()] = usedVarsChainPHP.toStdString();
|
|
}
|
|
} else if ((keywordPHPprevString.toLower() == "self" || keywordPHPprevString.toLower() == "static") && keywordPHPprevStringPrevChar != "$") {
|
|
clsPropsIterator = clsProps.find(varName.toStdString());
|
|
if (clsPropsIterator != clsProps.end()) {
|
|
known = true;
|
|
}
|
|
}
|
|
}
|
|
if (isObjectContext) {
|
|
QString varName = "$" + keywordStringPHP;
|
|
if (keywordPHPprevString.toLower() == "this" && keywordPHPprevStringPrevChar == "$") {
|
|
clsPropsIterator = clsProps.find(varName.toStdString());
|
|
if (clsPropsIterator != clsProps.end()) {
|
|
known = true;
|
|
}
|
|
}
|
|
}
|
|
if (!known) {
|
|
bool unused = false;
|
|
if (keywordPHPprevChar == "$" && ((keywordPHPprevString.toLower() != "self" && keywordPHPprevString.toLower() != "static") || keywordPHPprevStringPrevChar == "$")) {
|
|
QString ns = "\\";
|
|
if (nsNamePHP.size() > 0) ns += nsNamePHP + "\\";
|
|
QString _clsName = clsNamePHP.size() > 0 ? ns + clsNamePHP : "";
|
|
QString k = _clsName + "::" + funcNamePHP;
|
|
QString varName = keywordPHPprevChar + keywordStringPHP;
|
|
unusedVarsIterator = unusedVars.find((k + "::" + varName).toStdString());
|
|
if (unusedVarsIterator != unusedVars.end() && unusedVarsIterator->second == keywordPHPStart) {
|
|
unused = true;
|
|
} else if (expectedFuncNamePHP.size() > 0) {
|
|
k = _clsName + "::" + expectedFuncNamePHP;
|
|
unusedVarsIterator = unusedVars.find((k + "::" + varName).toStdString());
|
|
if (unusedVarsIterator != unusedVars.end() && unusedVarsIterator->second == keywordPHPStart) {
|
|
unused = true;
|
|
}
|
|
}
|
|
}
|
|
if (unused) highlightString(keywordPHPStart, keywordPHPLength, HW->unusedVariableFormat);
|
|
else highlightString(keywordPHPStart, keywordPHPLength, HW->variableFormat);
|
|
} else {
|
|
highlightString(keywordPHPStart, keywordPHPLength, HW->knownVariableFormat);
|
|
}
|
|
} else if (keywordPHPprevChar == ":" && keywordPHPprevString.size() > 0 && !isBigFile) {
|
|
QString k = keywordPHPprevString.toLower()+"::"+keywordStringPHP;
|
|
HW->phpClassWordsCSIterator = HW->phpClassWordsCS.find(k.toStdString());
|
|
if (HW->phpClassWordsCSIterator != HW->phpClassWordsCS.end()) {
|
|
QTextCharFormat format = HW->phpClassWordsCSIterator->second;
|
|
highlightString(keywordPHPStart, keywordPHPLength, format);
|
|
}
|
|
}
|
|
if (keywordPHPprevChar != "$" && !isObjectContext && keywordStringPHP.size()>0 && !isBigFile) {
|
|
// namespace scope
|
|
if (keywordStringPHP.size() > 0 && (keywordStringPHP.toLower() == "namespace" && expectedNsNamePHP.size() == 0)) {
|
|
expectedNsNamePHP = "\\";
|
|
}
|
|
// class scope
|
|
if (keywordStringPHP.size() > 0 && (((keywordStringPHP.toLower() == "class" || keywordStringPHP.toLower() == "interface" || keywordStringPHP.toLower() == "trait") && expectedClsNamePHP.size() == 0) || expectedClsNamePHP.toLower() == "class" || expectedClsNamePHP.toLower() == "interface" || expectedClsNamePHP.toLower() == "trait")) {
|
|
expectedClsNamePHP = keywordStringPHP;
|
|
}
|
|
// function scope
|
|
if (keywordStringPHP.size() > 0 && ((keywordStringPHP.toLower() == "function" && expectedFuncNamePHP.size() == 0) || expectedFuncNamePHP.toLower() == "function")) {
|
|
expectedFuncNamePHP = keywordStringPHP;
|
|
expectedFuncParsPHP = parensPHP;
|
|
expectedFuncArgsPHP.clear();
|
|
expectedFuncArgsPHPPositions.clear();
|
|
expectedFuncArgsPHPBlocks.clear();
|
|
}
|
|
}
|
|
keywordPHPprevString = keywordStringPHP;
|
|
keywordPHPprevStringPrevChar = keywordPHPprevChar;
|
|
keywordPHPprevPrevChar = c;
|
|
keywordPHPprevChar = c;
|
|
keywordPHPStartPrev = keywordPHPStart;
|
|
keywordPHPLengthPrev = keywordPHPLength;
|
|
}
|
|
if (c == ';') {
|
|
keywordPHPprevString = "";
|
|
keywordPHPprevStringPrevChar = "";
|
|
isGlobalPHP = false;
|
|
}
|
|
if (keywordPHPStartPrev>=0 && keywordPHPLengthPrev>0) {
|
|
// php functions
|
|
if (c.toLatin1() == '(') {
|
|
highlightString(keywordPHPStartPrev, keywordPHPLengthPrev, HW->functionFormat);
|
|
keywordPHPStartPrev = -1;
|
|
keywordPHPLengthPrev = -1;
|
|
} else if (!isWSpace) {
|
|
keywordPHPStartPrev = -1;
|
|
keywordPHPLengthPrev = -1;
|
|
}
|
|
}
|
|
|
|
// php curly brackets
|
|
if (stringSQOpenedPHP < 0 && stringDQOpenedPHP < 0 && stringBOpened < 0 && commentSLOpenedPHP < 0 && commentMLOpenedPHP < 0 && keywordPHPOpened < 0 && c.toLatin1() == '{') {
|
|
bracesPHP++;
|
|
// open namespace scope
|
|
if (expectedNsNamePHP.size() > 0) {
|
|
if (nsStartsPHP.size() > nsEndsPHP.size()) nsEndsPHP.append(pos);
|
|
QString cNsNamePHP = nsNamePHP;
|
|
int cNsScopePHP = nsScopePHP;
|
|
if (nsScopePHP < 0) cNsNamePHP = "";
|
|
nsNamePHP = expectedNsNamePHP.mid(1).trimmed();
|
|
if (nsNamePHP.size() > 0 && nsNamePHP[0] == "\\") nsNamePHP = nsNamePHP.mid(1).trimmed();
|
|
if (nsNamePHP.size() > 0) {
|
|
if (cNsNamePHP.size() > 0) nsNamePHP = cNsNamePHP + "\\" + nsNamePHP;
|
|
nsNamesPHP.append(nsNamePHP);
|
|
nsStartsPHP.append(pos+1);
|
|
nsScopePHP = bracesPHP-1;
|
|
if (nsChainPHP.size() > 0) nsChainPHP += ",";
|
|
nsChainPHP += cNsNamePHP;
|
|
nsScopeChainPHP.append(cNsScopePHP);
|
|
} else {
|
|
nsScopePHP = -1;
|
|
}
|
|
expectedNsNamePHP = "";
|
|
}
|
|
// open class scope
|
|
if (expectedClsNamePHP.size() > 0) {
|
|
QString cClsNamePHP = clsNamePHP;
|
|
int cClsScopePHP = clsScopePHP;
|
|
if (clsScopePHP < 0) cClsNamePHP = "";
|
|
if (expectedClsNamePHP == "class" || expectedClsNamePHP == "implements" || expectedClsNamePHP == "extends") expectedClsNamePHP = "anonymous class";
|
|
if (clsStartsPHP.size() > clsEndsPHP.size()) clsEndsPHP.append(pos);
|
|
clsNamePHP = expectedClsNamePHP;
|
|
clsScopePHP = bracesPHP-1;
|
|
clsNamesPHP.append(clsNamePHP);
|
|
clsStartsPHP.append(pos+1);
|
|
if (clsChainPHP.size() > 0) clsChainPHP += ",";
|
|
clsChainPHP += cClsNamePHP;
|
|
clsScopeChainPHP.append(cClsScopePHP);
|
|
expectedClsNamePHP = "";
|
|
// variables
|
|
if (cClsNamePHP.size() > 0 || funcNamePHP.size() > 0) {
|
|
varsChainsPHP.append(varsChainPHP);
|
|
usedVarsChainsPHP.append(usedVarsChainPHP);
|
|
} else {
|
|
varsGlobChainPHP = varsChainPHP;
|
|
usedVarsGlobChainPHP = usedVarsChainPHP;
|
|
}
|
|
if (clsOpenPHP) {
|
|
QStringList varsChainList = varsChainPHP.split(",");
|
|
for (int i=0; i<varsChainList.size(); i++) {
|
|
QString varName = varsChainList.at(i);
|
|
clsPropsIterator = clsProps.find(varName.toStdString());
|
|
if (clsPropsIterator == clsProps.end()) {
|
|
if (varsClsChainPHP.size() > 0) varsClsChainPHP += ",";
|
|
varsClsChainPHP += varName;
|
|
}
|
|
}
|
|
}
|
|
varsChainPHP = "";
|
|
usedVarsChainPHP = "";
|
|
variables.clear();
|
|
usedVariables.clear();
|
|
expectedFuncArgsPHP.clear();
|
|
expectedFuncArgsPHPPositions.clear();
|
|
expectedFuncArgsPHPBlocks.clear();
|
|
clsOpensPHP.append(clsOpenPHP);
|
|
clsOpenPHP = true;
|
|
if (varsClsOpenChainPHP.size() > 0 && varsClsChainPHP.size() > 0) varsClsOpenChainPHP += ",";
|
|
varsClsOpenChainPHP += varsClsChainPHP;
|
|
clsPropsChainPHP.append(varsClsChainPHP);
|
|
varsClsChainPHP = "";
|
|
}
|
|
// open function scope
|
|
if (expectedFuncNamePHP.size() > 0 && expectedFuncParsPHP == parensPHP) {
|
|
QString cFuncNamePHP = funcNamePHP;
|
|
int cFuncScopePHP = funcScopePHP;
|
|
if (funcScopePHP < 0) cFuncNamePHP = "";
|
|
if (funcStartsPHP.size() > funcEndsPHP.size()) funcEndsPHP.append(pos);
|
|
funcNamePHP = expectedFuncNamePHP;
|
|
funcScopePHP = bracesPHP-1;
|
|
funcNamesPHP.append(funcNamePHP);
|
|
funcStartsPHP.append(pos+1);
|
|
if (funcChainPHP.size() > 0) funcChainPHP += ",";
|
|
funcChainPHP += cFuncNamePHP;
|
|
funcScopeChainPHP.append(cFuncScopePHP);
|
|
expectedFuncNamePHP = "";
|
|
expectedFuncParsPHP = -1;
|
|
// variables
|
|
if (cFuncNamePHP.size() > 0 || clsNamePHP.size() > 0) {
|
|
varsChainsPHP.append(varsChainPHP);
|
|
usedVarsChainsPHP.append(usedVarsChainPHP);
|
|
} else {
|
|
varsGlobChainPHP = varsChainPHP;
|
|
usedVarsGlobChainPHP = usedVarsChainPHP;
|
|
}
|
|
clsPropsChainPHP.append(varsClsChainPHP);
|
|
if (clsOpenPHP) {
|
|
varsClsChainPHP = varsChainPHP;
|
|
clsProps = variables;
|
|
}
|
|
varsChainPHP = "";
|
|
usedVarsChainPHP = "";
|
|
variables.clear();
|
|
usedVariables.clear();
|
|
for (int i=0; i<expectedFuncArgsPHP.size(); i++) {
|
|
QString varName = expectedFuncArgsPHP.at(i);
|
|
if (varsChainPHP.size() > 0) varsChainPHP += ",";
|
|
varsChainPHP += varName;
|
|
variables[varName.toStdString()] = varName.toStdString();
|
|
QString ns = "\\";
|
|
if (nsNamePHP.size() > 0) ns += nsNamePHP + "\\";
|
|
QString _clsName = clsNamePHP.size() > 0 ? ns + clsNamePHP : "";
|
|
QString k = _clsName + "::" + funcNamePHP;
|
|
// save to known vars
|
|
if (highlightVarsMode || firstRunMode) {
|
|
knownVars[k.toStdString()] = varsChainPHP.toStdString();
|
|
QString kk = k + "::" + varName;
|
|
int eP = -1;
|
|
if (expectedFuncArgsPHPPositions.size() == expectedFuncArgsPHP.size()) {
|
|
eP = expectedFuncArgsPHPPositions.at(i);
|
|
}
|
|
knownVarsPositions[kk.toStdString()] = eP;
|
|
int eB = -1;
|
|
if (expectedFuncArgsPHPBlocks.size() == expectedFuncArgsPHP.size()) {
|
|
eB = expectedFuncArgsPHPBlocks.at(i);
|
|
}
|
|
knownVarsBlocks[kk.toStdString()] = eB;
|
|
usedVars[k.toStdString()] = usedVarsChainPHP.toStdString();
|
|
}
|
|
}
|
|
expectedFuncArgsPHP.clear();
|
|
expectedFuncArgsPHPPositions.clear();
|
|
expectedFuncArgsPHPBlocks.clear();
|
|
clsOpensPHP.append(clsOpenPHP);
|
|
clsOpenPHP = false;
|
|
// save to known functions
|
|
QString ns = "\\";
|
|
if (nsNamePHP.size() > 0) ns += nsNamePHP + "\\";
|
|
QString _clsName = clsNamePHP.size() > 0 ? ns + clsNamePHP : "";
|
|
QString k = _clsName + "::" + funcNamePHP;
|
|
knownFunctions[k.toStdString()] = funcNamePHP.toStdString();
|
|
}
|
|
} else if (stringSQOpenedPHP < 0 && stringDQOpenedPHP < 0 && stringBOpened < 0 && commentSLOpenedPHP < 0 && commentMLOpenedPHP < 0 && keywordPHPOpened < 0 && c.toLatin1() == '}') {
|
|
bracesPHP--;
|
|
if (bracesPHP < 0) bracesPHP = 0;
|
|
// close namespace scope
|
|
if (nsNamePHP.size() > 0 && nsScopePHP >= 0 && nsScopePHP == bracesPHP) {
|
|
nsNamePHP = "";
|
|
nsScopePHP = -1;
|
|
nsEndsPHP.append(pos);
|
|
expectedNsNamePHP = "";
|
|
// set parent namespace
|
|
int parentNsScopePHP = -1;
|
|
QString parentNsPHP = "", parentNsChainPHP = "";
|
|
if (!nsScopeChainPHP.isEmpty()) {
|
|
parentNsScopePHP = nsScopeChainPHP.last();
|
|
nsScopeChainPHP.removeLast();
|
|
QStringList nsChainListPHP = nsChainPHP.split(",");
|
|
parentNsPHP = nsChainListPHP.last();
|
|
for (int i=0; i<nsChainListPHP.size()-1; i++) {
|
|
if (parentNsChainPHP.size() > 0) parentNsChainPHP += ",";
|
|
parentNsChainPHP += nsChainListPHP.at(i);
|
|
}
|
|
if (parentNsScopePHP >= 0 && parentNsPHP.size() > 0) {
|
|
nsNamePHP = parentNsPHP;
|
|
nsChainPHP = parentNsChainPHP;
|
|
nsNamesPHP.append(nsNamePHP);
|
|
nsStartsPHP.append(pos+1);
|
|
nsScopePHP = parentNsScopePHP;
|
|
}
|
|
}
|
|
}
|
|
// close class scope
|
|
if (clsNamePHP.size() > 0 && clsScopePHP >= 0 && clsScopePHP == bracesPHP) {
|
|
clsNamePHP = "";
|
|
clsScopePHP = -1;
|
|
clsEndsPHP.append(pos);
|
|
expectedClsNamePHP = "";
|
|
// set parent cls
|
|
int parentClsScopePHP = -1;
|
|
QString parentClsPHP = "", parentClsChainPHP = "";
|
|
if (!clsScopeChainPHP.isEmpty()) {
|
|
parentClsScopePHP = clsScopeChainPHP.last();
|
|
clsScopeChainPHP.removeLast();
|
|
QStringList clsChainListPHP = clsChainPHP.split(",");
|
|
parentClsPHP = clsChainListPHP.last();
|
|
for (int i=0; i<clsChainListPHP.size()-1; i++) {
|
|
if (parentClsChainPHP.size() > 0) parentClsChainPHP += ",";
|
|
parentClsChainPHP += clsChainListPHP.at(i);
|
|
}
|
|
if (parentClsScopePHP >= 0 && parentClsPHP.size() > 0) {
|
|
clsNamePHP = parentClsPHP;
|
|
clsChainPHP = parentClsChainPHP;
|
|
clsNamesPHP.append(clsNamePHP);
|
|
clsStartsPHP.append(pos+1);
|
|
clsScopePHP = parentClsScopePHP;
|
|
}
|
|
}
|
|
// restore variables
|
|
varsChainPHP = "";
|
|
usedVarsChainPHP = "";
|
|
variables.clear();
|
|
usedVariables.clear();
|
|
if (!varsChainsPHP.isEmpty()) {
|
|
varsChainPHP = varsChainsPHP.last();
|
|
varsChainsPHP.removeLast();
|
|
} else if (clsNamePHP.size() == 0 && funcNamePHP.size() == 0) {
|
|
varsChainPHP = varsGlobChainPHP;
|
|
}
|
|
if (!usedVarsChainsPHP.isEmpty()) {
|
|
usedVarsChainPHP = usedVarsChainsPHP.last();
|
|
usedVarsChainsPHP.removeLast();
|
|
} else if (clsNamePHP.size() == 0 && funcNamePHP.size() == 0) {
|
|
usedVarsChainPHP = usedVarsGlobChainPHP;
|
|
}
|
|
if (varsChainPHP.size() > 0) {
|
|
QStringList varsChainList = varsChainPHP.split(",");
|
|
for (int i=0; i<varsChainList.size(); i++) {
|
|
QString varName = varsChainList.at(i);
|
|
variables[varName.toStdString()] = varName.toStdString();
|
|
}
|
|
}
|
|
if (usedVarsChainPHP.size() > 0) {
|
|
QStringList varsChainList = usedVarsChainPHP.split(",");
|
|
for (int i=0; i<varsChainList.size(); i++) {
|
|
QString varName = varsChainList.at(i);
|
|
usedVariables[varName.toStdString()] = varName.toStdString();
|
|
}
|
|
}
|
|
if (!clsPropsChainPHP.isEmpty()) {
|
|
varsClsChainPHP = clsPropsChainPHP.last();
|
|
clsPropsChainPHP.removeLast();
|
|
for (int i=0; i<varsClsChainPHP.size(); i++) {
|
|
QString varName = varsClsChainPHP.at(i);
|
|
clsProps[varName.toStdString()] = varName.toStdString();
|
|
}
|
|
} else {
|
|
varsClsChainPHP = "";
|
|
clsProps.clear();
|
|
}
|
|
if (!clsOpensPHP.isEmpty()) {
|
|
clsOpenPHP = clsOpensPHP.last();
|
|
clsOpensPHP.removeLast();
|
|
} else {
|
|
clsOpenPHP = false;
|
|
}
|
|
}
|
|
// close function scope
|
|
if (funcNamePHP.size() > 0 && funcScopePHP >= 0 && funcScopePHP == bracesPHP) {
|
|
funcNamePHP = "";
|
|
funcScopePHP = -1;
|
|
funcEndsPHP.append(pos);
|
|
expectedFuncNamePHP = "";
|
|
expectedFuncParsPHP = -1;
|
|
expectedFuncArgsPHP.clear();
|
|
expectedFuncArgsPHPPositions.clear();
|
|
expectedFuncArgsPHPBlocks.clear();
|
|
// set parent function
|
|
int parentFuncScopePHP = -1;
|
|
QString parentFuncPHP = "", parentFuncChainPHP = "";
|
|
if (!funcScopeChainPHP.isEmpty()) {
|
|
parentFuncScopePHP = funcScopeChainPHP.last();
|
|
funcScopeChainPHP.removeLast();
|
|
QStringList funcChainListPHP = funcChainPHP.split(",");
|
|
parentFuncPHP = funcChainListPHP.last();
|
|
for (int i=0; i<funcChainListPHP.size()-1; i++) {
|
|
if (parentFuncChainPHP.size() > 0) parentFuncChainPHP += ",";
|
|
parentFuncChainPHP += funcChainListPHP.at(i);
|
|
}
|
|
if (parentFuncScopePHP >= 0 && parentFuncPHP.size() > 0) {
|
|
funcNamePHP = parentFuncPHP;
|
|
funcChainPHP = parentFuncChainPHP;
|
|
funcNamesPHP.append(funcNamePHP);
|
|
funcStartsPHP.append(pos+1);
|
|
funcScopePHP = parentFuncScopePHP;
|
|
}
|
|
}
|
|
// restore variables
|
|
varsChainPHP = "";
|
|
usedVarsChainPHP = "";
|
|
variables.clear();
|
|
usedVariables.clear();
|
|
if (!varsChainsPHP.isEmpty()) {
|
|
varsChainPHP = varsChainsPHP.last();
|
|
varsChainsPHP.removeLast();
|
|
} else if (clsNamePHP.size() == 0 && funcNamePHP.size() == 0) {
|
|
varsChainPHP = varsGlobChainPHP;
|
|
}
|
|
if (!usedVarsChainsPHP.isEmpty()) {
|
|
usedVarsChainPHP = usedVarsChainsPHP.last();
|
|
usedVarsChainsPHP.removeLast();
|
|
} else if (clsNamePHP.size() == 0 && funcNamePHP.size() == 0) {
|
|
usedVarsChainPHP = usedVarsGlobChainPHP;
|
|
}
|
|
if (varsChainPHP.size() > 0) {
|
|
QStringList varsChainList = varsChainPHP.split(",");
|
|
for (int i=0; i<varsChainList.size(); i++) {
|
|
QString varName = varsChainList.at(i);
|
|
variables[varName.toStdString()] = varName.toStdString();
|
|
}
|
|
}
|
|
if (usedVarsChainPHP.size() > 0) {
|
|
QStringList varsChainList = usedVarsChainPHP.split(",");
|
|
for (int i=0; i<varsChainList.size(); i++) {
|
|
QString varName = varsChainList.at(i);
|
|
usedVariables[varName.toStdString()] = varName.toStdString();
|
|
}
|
|
}
|
|
if (!clsPropsChainPHP.isEmpty()) {
|
|
varsClsChainPHP = clsPropsChainPHP.last();
|
|
clsPropsChainPHP.removeLast();
|
|
for (int i=0; i<varsClsChainPHP.size(); i++) {
|
|
QString varName = varsClsChainPHP.at(i);
|
|
clsProps[varName.toStdString()] = varName.toStdString();
|
|
}
|
|
} else {
|
|
varsClsChainPHP = "";
|
|
clsProps.clear();
|
|
}
|
|
if (!clsOpensPHP.isEmpty()) {
|
|
clsOpenPHP = clsOpensPHP.last();
|
|
clsOpensPHP.removeLast();
|
|
} else {
|
|
clsOpenPHP = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// expected namespace scope
|
|
if (expectedNsNamePHP.size() > 0 && c.toLatin1() != ';') {
|
|
expectedNsNamePHP += c;
|
|
} else if (expectedNsNamePHP.size() > 0 && c.toLatin1() == ';') {
|
|
// open namespace without scope
|
|
if (nsStartsPHP.size() > nsEndsPHP.size()) {
|
|
nsEndsPHP.append(pos);
|
|
}
|
|
nsNamePHP = expectedNsNamePHP.mid(1).trimmed();
|
|
if (nsNamePHP.size() > 0 && nsNamePHP[0] == "\\") nsNamePHP = nsNamePHP.mid(1).trimmed();
|
|
nsScopePHP = -1;
|
|
if (nsNamePHP.size() > 0) {
|
|
nsNamesPHP.append(nsNamePHP);
|
|
nsChainPHP = "";
|
|
nsScopeChainPHP.clear();
|
|
nsStartsPHP.append(pos+1);
|
|
}
|
|
expectedNsNamePHP = "";
|
|
}
|
|
// unexpected class scope
|
|
if (expectedClsNamePHP.size() > 0 && expectedClsNamePHP.toLower() == "class" && c.toLatin1() == '(') {
|
|
expectedClsNamePHP = "anonymous class";
|
|
} else if (expectedClsNamePHP.size() > 0 && c.toLatin1() == ';') {
|
|
expectedClsNamePHP = "";
|
|
}
|
|
// unexpected function scope
|
|
if (expectedFuncNamePHP.size() > 0 && expectedFuncNamePHP.toLower() == "function" && c.toLatin1() == '(' && expectedFuncParsPHP == parensPHP) {
|
|
expectedFuncNamePHP = "anonymous function";
|
|
} else if (expectedFuncNamePHP.size() > 0 && c.toLatin1() == ';' && expectedFuncParsPHP == parensPHP) {
|
|
expectedFuncNamePHP = "";
|
|
expectedFuncParsPHP = -1;
|
|
}
|
|
|
|
// php parentheses
|
|
if (stringSQOpenedPHP < 0 && stringDQOpenedPHP < 0 && stringBOpened < 0 && commentSLOpenedPHP < 0 && commentMLOpenedPHP < 0 && keywordPHPOpened < 0 && c.toLatin1() == '(') {
|
|
parensPHP++;
|
|
operatorsPHP[parensPHP] = "";
|
|
} else if (stringSQOpenedPHP < 0 && stringDQOpenedPHP < 0 && stringBOpened < 0 && commentSLOpenedPHP < 0 && commentMLOpenedPHP < 0 && keywordPHPOpened < 0 && c.toLatin1() == ')') {
|
|
operatorsPHP[parensPHP] = "";
|
|
parensPHP--;
|
|
if (parensPHP < 0) parensPHP = 0;
|
|
}
|
|
|
|
// saving special chars data
|
|
if (stringSQOpenedPHP < 0 && stringDQOpenedPHP < 0 && stringBOpened < 0 && commentSLOpenedPHP < 0 && commentMLOpenedPHP < 0 && keywordPHPOpened < 0 && (c.toLatin1() == '{' || c.toLatin1() == '}' || c.toLatin1() == '(' || c.toLatin1() == ')' || c.toLatin1() == '[' || c.toLatin1() == ']')) {
|
|
addSpecialChar(c, pos);
|
|
}
|
|
|
|
// tabs, spaces, semicolons, commas
|
|
if (stringSQOpenedPHP < 0 && stringDQOpenedPHP < 0 && stringBOpened < 0 && commentSLOpenedPHP < 0 && commentMLOpenedPHP < 0 && keywordPHPOpened < 0) {
|
|
if (highlightTabs && c.toLatin1() == '\t') {
|
|
highlightChar(pos, HW->tabFormat);
|
|
} else if (highlightSpaces && c.toLatin1() == ' ') {
|
|
highlightChar(pos, HW->spaceFormat);
|
|
}
|
|
if (!isBigFile && (c.toLatin1() == ';' || c.toLatin1() == ',' || c.toLatin1() == '{' || c.toLatin1() == '}' || c.toLatin1() == '(' || c.toLatin1() == ')' || c.toLatin1() == '[' || c.toLatin1() == ']' || c.toLatin1() == '\\' || c.toLatin1() == '@')) {
|
|
highlightChar(pos, HW->punctuationFormat);
|
|
}
|
|
}
|
|
|
|
// "and / or" operators check
|
|
if (stringSQOpenedPHP < 0 && stringDQOpenedPHP < 0 && stringBOpened < 0 && commentSLOpenedPHP < 0 && commentMLOpenedPHP < 0 && keywordPHPOpened < 0) {
|
|
if (expectAndSignPHP && c.toLatin1() == '&') {
|
|
operatorsPHPIterator = operatorsPHP.find(parensPHP);
|
|
if (operatorsPHPIterator != operatorsPHP.end() && operatorsPHPIterator->second == "|") {
|
|
highlightError(pos - 1, 2);
|
|
} else {
|
|
operatorsPHP[parensPHP] = "&";
|
|
}
|
|
operatorsChainPHP += "&";
|
|
}
|
|
if (expectOrSignPHP && c.toLatin1() == '|') {
|
|
operatorsPHPIterator = operatorsPHP.find(parensPHP);
|
|
if (operatorsPHPIterator != operatorsPHP.end() && operatorsPHPIterator->second == "&") {
|
|
highlightError(pos - 1, 2);
|
|
} else {
|
|
operatorsPHP[parensPHP] = "|";
|
|
}
|
|
operatorsChainPHP += "|";
|
|
}
|
|
if (c.toLatin1() == '&') expectAndSignPHP = true;
|
|
else expectAndSignPHP = false;
|
|
if (c.toLatin1() == '|') expectOrSignPHP = true;
|
|
else expectOrSignPHP = false;
|
|
if (c.toLatin1() == ';' || c.toLatin1() == ',') {
|
|
operatorsPHPIterator = operatorsPHP.find(parensPHP);
|
|
if (operatorsPHPIterator != operatorsPHP.end() && operatorsPHPIterator->second != "") {
|
|
operatorsPHP[parensPHP] = "";
|
|
operatorsChainPHP += ";";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Highlight::parseUnknown(const QChar &c, int pos, bool isAlpha, bool isAlnum, bool isWSpace, bool isLast, int & keywordUnknownStartPrev, int & keywordUnknownLengthPrev)
|
|
{
|
|
if (mode != MODE_UNKNOWN) return;
|
|
|
|
bool stringSQchangedUnknown = false;
|
|
bool stringDQchangedUnknown = false;
|
|
bool commentsSLchangedUnknown = false;
|
|
bool commentsMLchangedUnknown = false;
|
|
|
|
if (!isTextMode()) {
|
|
// string (single quote)
|
|
stringSQchangedUnknown = detectStringSQUnknown(c, pos);
|
|
if ((stringSQOpenedUnknown>=0 && state == STATE_STRING_SQ_UNKNOWN) || stringSQchangedUnknown) {
|
|
highlightChar(pos, HW->stringFormat);
|
|
}
|
|
|
|
// string (double quote)
|
|
stringDQchangedUnknown = detectStringDQUnknown(c, pos);
|
|
if ((stringDQOpenedUnknown>=0 && state == STATE_STRING_DQ_UNKNOWN)|| stringDQchangedUnknown) {
|
|
highlightChar(pos, HW->stringFormat);
|
|
}
|
|
|
|
// comments (single-line)
|
|
commentsSLchangedUnknown = detectSLCommentUnknown(c, pos);
|
|
if (commentSLOpenedUnknown>=0 || commentsSLchangedUnknown) {
|
|
highlightChar(pos, HW->singleLineCommentFormat);
|
|
if (commentSLOpenedUnknown>=0 && commentsSLchangedUnknown && pos>0 && c.toLatin1() != '#' && c.toLatin1() != ';') {
|
|
highlightChar(pos-1, HW->singleLineCommentFormat);
|
|
}
|
|
}
|
|
|
|
// comments (multi-line)
|
|
commentsMLchangedUnknown = detectMLCommentUnknown(c, pos);
|
|
if ((commentMLOpenedUnknown>=0 && state == STATE_COMMENT_ML_UNKNOWN)|| commentsMLchangedUnknown) {
|
|
highlightChar(pos, HW->multiLineCommentFormat);
|
|
if (commentMLOpenedUnknown>=0 && state == STATE_COMMENT_ML_UNKNOWN && commentsMLchangedUnknown && pos>0) {
|
|
highlightChar(pos-1, HW->multiLineCommentFormat);
|
|
}
|
|
}
|
|
|
|
// keywords
|
|
int keywordUnknownStart = detectKeywordUnknown(c, pos, isAlpha, isAlnum, isLast);
|
|
if (keywordUnknownStart>=0) {
|
|
int keywordUnknownLength = pos-keywordUnknownStart;
|
|
if (isLast && (isAlnum || c.toLatin1() == '-')) keywordUnknownLength += 1;
|
|
bool known = false;
|
|
if (keywordStringUnknown.size()>0) {
|
|
// general keywords
|
|
HW->generalwordsIterator = HW->generalwords.find(keywordStringUnknown.toLower().toStdString());
|
|
if (HW->generalwordsIterator != HW->generalwords.end()) {
|
|
QTextCharFormat format = HW->generalwordsIterator->second;
|
|
highlightString(keywordUnknownStart, keywordUnknownLength, format);
|
|
keywordUnknownStart = -1;
|
|
known = true;
|
|
}
|
|
}
|
|
if (!known && !isBigFile) {
|
|
if (keywordUnknownprevChar == "@") {
|
|
highlightString(keywordUnknownStart, keywordUnknownLength, HW->punctuationFormat);
|
|
} else if (keywordJSprevChar != "." && c.toLatin1() == ':') {
|
|
highlightString(keywordUnknownStart, keywordUnknownLength, HW->propertyFormat);
|
|
}
|
|
}
|
|
if (keywordUnknownprevChar != ".") {
|
|
keywordUnknownStartPrev = keywordUnknownStart;
|
|
keywordUnknownLengthPrev = keywordUnknownLength;
|
|
}
|
|
keywordUnknownprevChar = c;
|
|
}
|
|
if (keywordUnknownStartPrev>=0 && keywordUnknownLengthPrev>0) {
|
|
// functions
|
|
if (c.toLatin1() == '(') {
|
|
highlightString(keywordUnknownStartPrev, keywordUnknownLengthPrev, HW->functionFormat);
|
|
}
|
|
if (!isWSpace) {
|
|
if (!isAlnum && c.toLatin1() != '-') {
|
|
keywordUnknownStartPrev = -1;
|
|
keywordUnknownLengthPrev = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (stringSQOpenedUnknown < 0 && stringDQOpenedUnknown < 0 && commentSLOpenedUnknown < 0 && commentMLOpenedUnknown < 0 && !commentsMLchangedUnknown && !commentsSLchangedUnknown && !stringSQchangedUnknown && !stringDQchangedUnknown) {
|
|
if (highlightTabs && c.toLatin1() == '\t') {
|
|
highlightChar(pos, HW->tabFormat);
|
|
} else if (highlightSpaces && c.toLatin1() == ' ') {
|
|
highlightChar(pos, HW->spaceFormat);
|
|
}
|
|
if (!isTextMode() && !isBigFile && (c.toLatin1() == ';' || c.toLatin1() == ',' || c.toLatin1() == '{' || c.toLatin1() == '}' || c.toLatin1() == '(' || c.toLatin1() == ')' || c.toLatin1() == '[' || c.toLatin1() == ']' || c.toLatin1() == '\\' || c.toLatin1() == '@' || c.toLatin1() == '&' || c.toLatin1() == '<' || c.toLatin1() == '>' || c.toLatin1() == '.' || c.toLatin1() == '?' || c.toLatin1() == ':' || c.toLatin1() == '%' || c.toLatin1() == '$' || c.toLatin1() == '^' || c.toLatin1() == '#' || c.toLatin1() == '@' || c.toLatin1() == '!' || c.toLatin1() == '\'' || c.toLatin1() == '"' || c.toLatin1() == '|' || c.toLatin1() == '~' || c.toLatin1() == '`')) {
|
|
highlightChar(pos, HW->punctuationFormat);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Highlight::updateState(const QChar & c, int pos, int & pState)
|
|
{
|
|
if (state == pState) return;
|
|
if (stateStarts.size()>stateEnds.size()) {
|
|
stateEnds.append(pos);
|
|
}
|
|
if (state != STATE_NONE) {
|
|
int stateStart = pos;
|
|
if (pos > 0 && (
|
|
state == STATE_COMMENT_ML_CSS ||
|
|
state == STATE_COMMENT_ML_JS ||
|
|
state == STATE_COMMENT_ML_PHP ||
|
|
state == STATE_COMMENT_SL_JS ||
|
|
state == STATE_COMMENT_ML_UNKNOWN
|
|
)) {
|
|
stateStart = pos - 1;
|
|
}
|
|
if (state == STATE_COMMENT_SL_PHP && c.toLatin1() != '#' && pos > 0) stateStart = pos - 1;
|
|
if (state == STATE_COMMENT_ML_HTML) stateStart = commentHTMLOpened;
|
|
if (state == STATE_STRING_HEREDOC || state == STATE_STRING_NOWDOC) stateStart = stringBStart;
|
|
if (state == STATE_COMMENT_SL_UNKNOWN && c.toLatin1() != '#' && c.toLatin1() != ';' && pos > 0) stateStart = pos - 1;
|
|
stateStart++;
|
|
if (stateStarts.size() > 0 && stateStarts.last() == stateStart &&
|
|
stateStarts.size() == stateIds.size() && stateStarts.size() == stateEnds.size()
|
|
) {
|
|
stateStarts.removeLast();
|
|
stateIds.removeLast();
|
|
stateEnds.removeLast();
|
|
}
|
|
stateStarts.append(stateStart);
|
|
stateIds.append(state);
|
|
}
|
|
pState = state;
|
|
}
|
|
|
|
void Highlight::openBlockDataLists()
|
|
{
|
|
if (modeType == MODE_MIXED && mode != MODE_HTML) {
|
|
modeStarts.append(0);
|
|
modeTags.append(mode);
|
|
}
|
|
if (state != STATE_NONE) {
|
|
stateStarts.append(0);
|
|
stateIds.append(state);
|
|
}
|
|
if (nsNamePHP.size() > 0) {
|
|
nsStartsPHP.append(0);
|
|
nsNamesPHP.append(nsNamePHP);
|
|
}
|
|
if (clsNamePHP.size() > 0 && clsScopePHP >= 0) {
|
|
clsStartsPHP.append(0);
|
|
clsNamesPHP.append(clsNamePHP);
|
|
}
|
|
if (funcNamePHP.size() > 0 && funcScopePHP >= 0) {
|
|
funcStartsPHP.append(0);
|
|
funcNamesPHP.append(funcNamePHP);
|
|
}
|
|
if (varsChainPHP.size() > 0) {
|
|
QStringList varsChainList = varsChainPHP.split(",");
|
|
for (int i=0; i<varsChainList.size(); i++) {
|
|
QString varName = varsChainList.at(i);
|
|
variables[varName.toStdString()] = varName.toStdString();
|
|
}
|
|
}
|
|
if (usedVarsChainPHP.size() > 0) {
|
|
QStringList varsChainList = usedVarsChainPHP.split(",");
|
|
for (int i=0; i<varsChainList.size(); i++) {
|
|
QString varName = varsChainList.at(i);
|
|
usedVariables[varName.toStdString()] = varName.toStdString();
|
|
}
|
|
}
|
|
if (varsClsChainPHP.size() > 0) {
|
|
QStringList varsClsChainList = varsClsChainPHP.split(",");
|
|
for (int i=0; i<varsClsChainList.size(); i++) {
|
|
QString varName = varsClsChainList.at(i);
|
|
clsProps[varName.toStdString()] = varName.toStdString();
|
|
}
|
|
}
|
|
if (clsNameJS.size() > 0 && clsScopeJS >= 0) {
|
|
clsStartsJS.append(0);
|
|
clsNamesJS.append(clsNameJS);
|
|
}
|
|
if (funcNameJS.size() > 0 && funcScopeJS >= 0) {
|
|
funcStartsJS.append(0);
|
|
funcNamesJS.append(funcNameJS);
|
|
}
|
|
if (mediaNameCSS.size() > 0 && mediaScopeCSS >= 0) {
|
|
mediaStartsCSS.append(0);
|
|
mediaNamesCSS.append(mediaNameCSS);
|
|
}
|
|
if (tagChainHTML.size() > 0) {
|
|
tagChainStartsHTML.append(0);
|
|
tagChainsHTML.append(tagChainHTML);
|
|
}
|
|
if (varsChainJS.size() > 0) {
|
|
QStringList varsChainList = varsChainJS.split(",");
|
|
for (int i=0; i<varsChainList.size(); i++) {
|
|
QString varName = varsChainList.at(i);
|
|
jsNames[varName.toStdString()] = varName.toStdString();
|
|
}
|
|
}
|
|
if (cssNamesChain.size() > 0) {
|
|
QStringList cssNamesChainList = cssNamesChain.split(",");
|
|
for (int i=0; i<cssNamesChainList.size(); i++) {
|
|
QString cssName = cssNamesChainList.at(i);
|
|
cssNames[cssName.toStdString()] = cssName.toStdString();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Highlight::closeBlockDataLists(int textSize)
|
|
{
|
|
if (modeType == MODE_MIXED && mode != MODE_HTML && modeStarts.size() > modeEnds.size()) {
|
|
modeEnds.append(textSize);
|
|
}
|
|
if (stateStarts.size()>stateEnds.size()) {
|
|
stateEnds.append(textSize);
|
|
}
|
|
if (nsStartsPHP.size()>nsEndsPHP.size()) {
|
|
nsEndsPHP.append(textSize);
|
|
}
|
|
if (clsStartsPHP.size()>clsEndsPHP.size()) {
|
|
clsEndsPHP.append(textSize);
|
|
}
|
|
if (funcStartsPHP.size()>funcEndsPHP.size()) {
|
|
funcEndsPHP.append(textSize);
|
|
}
|
|
if (clsStartsJS.size()>clsEndsJS.size()) {
|
|
clsEndsJS.append(textSize);
|
|
}
|
|
if (funcStartsJS.size()>funcEndsJS.size()) {
|
|
funcEndsJS.append(textSize);
|
|
}
|
|
if (mediaStartsCSS.size()>mediaEndsCSS.size()) {
|
|
mediaEndsCSS.append(textSize);
|
|
}
|
|
if (tagChainStartsHTML.size()>tagChainEndsHTML.size()) {
|
|
tagChainEndsHTML.append(textSize);
|
|
}
|
|
}
|
|
|
|
bool Highlight::isDirty()
|
|
{
|
|
return dirty;
|
|
}
|
|
|
|
void Highlight::rehighlight()
|
|
{
|
|
rehighlightBlockMode = true;
|
|
int blocksCount = doc->blockCount();
|
|
QTextBlock block = doc->findBlockByNumber(0);
|
|
if (!block.isValid()) return;
|
|
int startPos = block.position();
|
|
int progressPercent = 0;
|
|
do {
|
|
dirty = true;
|
|
highlightBlock(block, false);
|
|
if (highlightVarsMode || firstRunMode) {
|
|
int percent = (block.blockNumber()+1)*100 / blocksCount;
|
|
if (percent - progressPercent > 10) {
|
|
progressPercent = percent;
|
|
if (Helper::isQtVersionLessThan(5, 15, 0) || highlightVarsMode) {
|
|
doc->markContentsDirty(startPos, block.position() - startPos + block.length());
|
|
startPos = block.position() + block.length();
|
|
dirty = false;
|
|
}
|
|
emit progressChanged(percent);
|
|
}
|
|
}
|
|
block = block.next();
|
|
} while(block.isValid());
|
|
if (!block.isValid()) block = block.previous();
|
|
doc->markContentsDirty(startPos, block.position() - startPos + block.length());
|
|
dirty = false;
|
|
if (highlightVarsMode || firstRunMode) {
|
|
emit progressChanged(100);
|
|
}
|
|
rehighlightBlockMode = false;
|
|
}
|
|
|
|
void Highlight::resetHighlightBlock(QTextBlock & block)
|
|
{
|
|
HighlightData * blockData = dynamic_cast<HighlightData *>(block.userData());
|
|
if (blockData != nullptr) blockData->isNewBlock = true;
|
|
}
|
|
|
|
void Highlight::rehighlightBlock(QTextBlock & block)
|
|
{
|
|
rehighlightBlockMode = true;
|
|
highlightBlock(block, true);
|
|
rehighlightBlockMode = false;
|
|
}
|
|
|
|
void Highlight::highlightChanges(QTextCursor curs)
|
|
{
|
|
QTextBlock block = curs.block();
|
|
if (!block.isValid()) return;
|
|
int startPos = block.position();
|
|
do {
|
|
dirty = true;
|
|
const int stateBeforeHighlight = block.userState();
|
|
highlightBlock(block, false);
|
|
if (block.userState() == stateBeforeHighlight) break;
|
|
block = block.next();
|
|
} while(block.isValid());
|
|
if (!block.isValid()) block = block.previous();
|
|
doc->markContentsDirty(startPos, block.position() - startPos + block.length());
|
|
dirty = false;
|
|
}
|
|
|
|
void Highlight::highlightBlock(QTextBlock & block, bool markDirty)
|
|
{
|
|
formatChanges.clear();
|
|
formatChanges.fill(QTextCharFormat(), block.text().size());
|
|
cBlock = block;
|
|
blockData = dynamic_cast<HighlightData *>(block.userData());
|
|
QString text = block.text();
|
|
if (parseBlock(text)) {
|
|
applyFormatChanges(markDirty);
|
|
}
|
|
formatChanges.clear();
|
|
}
|
|
|
|
bool Highlight::parseBlock(const QString & text)
|
|
{
|
|
if (!enabled) return false;
|
|
|
|
reset();
|
|
if (modeType != MODE_MIXED) {
|
|
mode = modeType;
|
|
}
|
|
|
|
bool isNewBlock = false;
|
|
std::string _mode = mode;
|
|
std::string _prevMode = prevMode;
|
|
QString _stringBlock = stringBlock;
|
|
int _state = state;
|
|
int _prevState = prevState;
|
|
int _prevPrevState = prevPrevState;
|
|
QString _stringEscStringCSS = stringEscStringCSS;
|
|
QString _stringEscStringJS = stringEscStringJS;
|
|
QString _regexpEscStringJS = regexpEscStringJS;
|
|
QString _regexpPrevCharJs = regexpPrevCharJS;
|
|
int _bracesCSS = bracesCSS;
|
|
int _bracesJS = bracesJS;
|
|
int _bracesPHP = bracesPHP;
|
|
//int _parensCSS = parensCSS;
|
|
int _parensJS = parensJS;
|
|
int _parensPHP = parensPHP;
|
|
bool _keywordPHPScoped = keywordPHPScoped;
|
|
bool _keywordJSScoped = keywordJSScoped;
|
|
QString _exprEscStringJS = exprEscStringJS;
|
|
QString _stringEscVariableJS = stringEscVariableJS;
|
|
bool _hasMarkPoint = false; // used by editor
|
|
bool _isModified = false; // used by editor
|
|
QString _nsNamePHP = nsNamePHP;
|
|
QString _nsChainPHP = nsChainPHP;
|
|
QString _clsNamePHP = clsNamePHP;
|
|
QString _clsChainPHP = clsChainPHP;
|
|
QString _funcNamePHP = funcNamePHP;
|
|
QString _funcChainPHP = funcChainPHP;
|
|
QString _varsChainPHP = varsChainPHP;
|
|
QString _usedVarsChainPHP = usedVarsChainPHP;
|
|
QString _varsGlobChainPHP = varsGlobChainPHP;
|
|
QString _usedVarsGlobChainPHP = usedVarsGlobChainPHP;
|
|
QString _varsClsChainPHP = varsClsChainPHP;
|
|
QString _varsClsOpenChainPHP = varsClsOpenChainPHP;
|
|
QString _expectedNsNamePHP = expectedNsNamePHP;
|
|
QString _expectedClsNamePHP = expectedClsNamePHP;
|
|
QString _expectedFuncNamePHP = expectedFuncNamePHP;
|
|
QString _expectedFuncArgsPHPChain = expectedFuncArgsPHP.join(",");
|
|
int _expectedFuncParsPHP = expectedFuncParsPHP;
|
|
QString _expectedFuncNameJS = expectedFuncNameJS;
|
|
int _expectedFuncParsJS = expectedFuncParsJS;
|
|
QString _expectedFuncVarJS = expectedFuncVarJS;
|
|
QString _varsChainJS = varsChainJS;
|
|
QString _expectedMediaNameCSS = expectedMediaNameCSS;
|
|
int _expectedMediaParsCSS = expectedMediaParsCSS;
|
|
QString _funcNameJS = funcNameJS;
|
|
QString _funcChainJS = funcChainJS;
|
|
QString _expectedFuncArgsJSChain = expectedFuncArgsJS.join(",");
|
|
QString _mediaNameCSS = mediaNameCSS;
|
|
QString _tagChainHTML = tagChainHTML;
|
|
QString _cssNamesChain = cssNamesChain;
|
|
QString _operatorsChainPHP = operatorsChainPHP;
|
|
QString _operatorsChainJS = operatorsChainJS;
|
|
QString _expectedClsNameJS = expectedClsNameJS;
|
|
QString _clsNameJS = clsNameJS;
|
|
QString _clsChainJS = clsChainJS;
|
|
|
|
// load current block data
|
|
if (blockData == nullptr) {
|
|
blockData = new HighlightData();
|
|
isNewBlock = true;
|
|
if (!firstRunMode) _isModified = true; // used by editor
|
|
} else {
|
|
isNewBlock = blockData->isNewBlock;
|
|
_mode = blockData->mode.toStdString();
|
|
_prevMode = blockData->prevMode.toStdString();
|
|
_stringBlock = blockData->stringBlock;
|
|
_state = blockData->state;
|
|
_prevState = blockData->prevState;
|
|
_prevPrevState = blockData->prevPrevState;
|
|
_stringEscStringCSS = blockData->stringEscStringCSS;
|
|
_stringEscStringJS = blockData->stringEscStringJS;
|
|
_regexpEscStringJS = blockData->regexpEscStringJS;
|
|
_regexpPrevCharJs = blockData->regexpPrevCharJS;
|
|
_bracesCSS = blockData->bracesCSS;
|
|
_bracesJS = blockData->bracesJS;
|
|
_bracesPHP = blockData->bracesPHP;
|
|
//_parensCSS = blockData->parensCSS;
|
|
_parensJS = blockData->parensJS;
|
|
_parensPHP = blockData->parensPHP;
|
|
_keywordPHPScoped = blockData->keywordPHPScoped;
|
|
_keywordJSScoped = blockData->keywordJSScoped;
|
|
_exprEscStringJS = blockData->exprEscStringJS;
|
|
_stringEscVariableJS = blockData->stringEscVariableJS;
|
|
_hasMarkPoint = blockData->hasMarkPoint;
|
|
_isModified = blockData->isModified;
|
|
_nsNamePHP = blockData->nsNamePHP;
|
|
_nsChainPHP = blockData->nsChainPHP;
|
|
_clsNamePHP = blockData->clsNamePHP;
|
|
_clsChainPHP = blockData->clsChainPHP;
|
|
_funcNamePHP = blockData->funcNamePHP;
|
|
_funcChainPHP = blockData->funcChainPHP;
|
|
_varsChainPHP = blockData->varsChainPHP;
|
|
_usedVarsChainPHP = blockData->usedVarsChainPHP;
|
|
_varsGlobChainPHP = blockData->varsGlobChainPHP;
|
|
_usedVarsGlobChainPHP = blockData->usedVarsGlobChainPHP;
|
|
_varsClsChainPHP = blockData->varsClsChainPHP;
|
|
_varsClsOpenChainPHP = blockData->varsClsOpenChainPHP;
|
|
_expectedNsNamePHP = blockData->expectedNsNamePHP;
|
|
_expectedClsNamePHP = blockData->expectedClsNamePHP;
|
|
_expectedFuncNamePHP = blockData->expectedFuncNamePHP;
|
|
_expectedFuncArgsPHPChain = blockData->expectedFuncArgsPHP.join(",");
|
|
_expectedFuncParsPHP = blockData->expectedFuncParsPHP;
|
|
_expectedFuncNameJS = blockData->expectedFuncNameJS;
|
|
_expectedFuncParsJS = blockData->expectedFuncParsJS;
|
|
_expectedFuncVarJS = blockData->expectedFuncVarJS;
|
|
_varsChainJS = blockData->varsChainJS;
|
|
_expectedMediaNameCSS = blockData->expectedMediaNameCSS;
|
|
_expectedMediaParsCSS = blockData->expectedMediaParsCSS;
|
|
_funcNameJS = blockData->funcNameJS;
|
|
_funcChainJS = blockData->funcChainJS;
|
|
_expectedFuncArgsJSChain = blockData->expectedFuncArgsJS.join(",");
|
|
_mediaNameCSS = blockData->mediaNameCSS;
|
|
_tagChainHTML = blockData->tagChainHTML;
|
|
_cssNamesChain = blockData->cssNamesChain;
|
|
_operatorsChainPHP = blockData->operatorsChainPHP;
|
|
_operatorsChainJS = blockData->operatorsChainJS;
|
|
_expectedClsNameJS = blockData->expectedClsNameJS;
|
|
_clsNameJS = blockData->clsNameJS;
|
|
_clsChainJS = blockData->clsChainJS;
|
|
}
|
|
|
|
if (!highlightVarsMode && !firstRunMode && !rehighlightBlockMode && lastVisibleBlockNumber >= 0 && cBlock.blockNumber() > lastVisibleBlockNumber + EXTRA_HIGHLIGHT_BLOCKS_COUNT) {
|
|
blockData->wantUpdate = true;
|
|
cBlock.setUserData(blockData);
|
|
return false;
|
|
}
|
|
|
|
blockData->reset();
|
|
restoreState();
|
|
|
|
// open data lists
|
|
openBlockDataLists();
|
|
|
|
std::string pMode = mode;
|
|
int pState = state;
|
|
int keywordCSSStartPrev = -1, keywordCSSLengthPrev = -1, keywordJSStartPrev = -1, keywordJSLengthPrev = -1, keywordPHPStartPrev = -1, keywordPHPLengthPrev = -1, keywordUnknownStartPrev = -1, keywordUnknownLengthPrev = -1;
|
|
bool cssValuePart = true;
|
|
for (int i=0; i<text.size(); i++) {
|
|
const QChar & c = text[i];
|
|
bool isLast = (i == text.size()-1) ? true : false;
|
|
bool isAlpha = isalpha(c.toLatin1()) > 0 || c.toLatin1() == '_' ? true : false;
|
|
bool isAlnum = isalnum(c.toLatin1()) > 0 || c.toLatin1() == '_' ? true : false;
|
|
bool isWSpace = c.isSpace();
|
|
|
|
// detect highlight mode
|
|
if (parseMode(c, i, isWSpace, isLast, pMode, pState)) continue;
|
|
|
|
// html mode
|
|
parseHTML(c, (i>0 ? text[i-1] : '\0'), i, isAlpha, isAlnum, isLast);
|
|
|
|
// css mode
|
|
parseCSS(c, i, isAlpha, isAlnum, isWSpace, isLast, keywordCSSStartPrev, keywordCSSLengthPrev, cssValuePart);
|
|
|
|
// js mode
|
|
parseJS(c, i, isAlpha, isAlnum, isWSpace, isLast, keywordJSStartPrev, keywordJSLengthPrev);
|
|
|
|
// php mode
|
|
parsePHP(c, i, isAlpha, isAlnum, isWSpace, isLast, keywordPHPStartPrev, keywordPHPLengthPrev);
|
|
|
|
// unknown
|
|
parseUnknown(c, i, isAlpha, isAlnum, isWSpace, isLast, keywordUnknownStartPrev, keywordUnknownLengthPrev);
|
|
|
|
// state changes
|
|
updateState(c, i, pState);
|
|
}
|
|
|
|
// draw spell underline
|
|
highlightSpell();
|
|
|
|
// close data lists
|
|
closeBlockDataLists(text.size());
|
|
|
|
// Helper::log(Helper::intToStr(cBlock.blockNumber())+": "+QString::fromStdString(prevMode)+", "+QString::fromStdString(mode)+" : "+Helper::intToStr(prevState)+", "+Helper::intToStr(state)+"\n");
|
|
|
|
if (isNewBlock ||
|
|
mode != _mode ||
|
|
prevMode != _prevMode ||
|
|
state != _state ||
|
|
prevState != _prevState ||
|
|
prevPrevState != _prevPrevState ||
|
|
stringEscStringCSS != _stringEscStringCSS ||
|
|
stringEscStringJS != _stringEscStringJS ||
|
|
regexpEscStringJS != _regexpEscStringJS ||
|
|
regexpPrevCharJS != _regexpPrevCharJs ||
|
|
stringBlock != _stringBlock ||
|
|
_bracesCSS != bracesCSS ||
|
|
_bracesJS != bracesJS ||
|
|
_bracesPHP != bracesPHP ||
|
|
//_parensCSS != parensCSS ||
|
|
_parensJS != parensJS ||
|
|
_parensPHP != parensPHP ||
|
|
_keywordPHPScoped != keywordPHPScoped ||
|
|
_keywordJSScoped != keywordJSScoped ||
|
|
_exprEscStringJS != exprEscStringJS ||
|
|
_stringEscVariableJS != stringEscVariableJS ||
|
|
_nsNamePHP != nsNamePHP ||
|
|
_nsChainPHP != nsChainPHP ||
|
|
_clsNamePHP != clsNamePHP ||
|
|
_clsChainPHP != clsChainPHP ||
|
|
_funcNamePHP != funcNamePHP ||
|
|
_funcChainPHP != funcChainPHP ||
|
|
_varsChainPHP != varsChainPHP ||
|
|
_usedVarsChainPHP != usedVarsChainPHP ||
|
|
_varsGlobChainPHP != varsGlobChainPHP ||
|
|
_usedVarsGlobChainPHP != usedVarsGlobChainPHP ||
|
|
_varsClsChainPHP != varsClsChainPHP ||
|
|
_varsClsOpenChainPHP != varsClsOpenChainPHP ||
|
|
_expectedNsNamePHP != expectedNsNamePHP ||
|
|
_expectedClsNamePHP != expectedClsNamePHP ||
|
|
_expectedFuncNamePHP != expectedFuncNamePHP ||
|
|
_expectedFuncArgsPHPChain != expectedFuncArgsPHP.join(",") ||
|
|
_expectedFuncParsPHP != expectedFuncParsPHP ||
|
|
_expectedFuncNameJS != expectedFuncNameJS ||
|
|
_expectedFuncParsJS != expectedFuncParsJS ||
|
|
_expectedFuncVarJS != expectedFuncVarJS ||
|
|
_varsChainJS != varsChainJS ||
|
|
_expectedFuncArgsJSChain != expectedFuncArgsJS.join(",") ||
|
|
_expectedMediaNameCSS != expectedMediaNameCSS ||
|
|
_expectedMediaParsCSS != expectedMediaParsCSS ||
|
|
_funcNameJS != funcNameJS ||
|
|
_funcChainJS != funcChainJS ||
|
|
_mediaNameCSS != mediaNameCSS ||
|
|
_tagChainHTML != tagChainHTML ||
|
|
_cssNamesChain != cssNamesChain ||
|
|
_operatorsChainPHP != operatorsChainPHP ||
|
|
_operatorsChainJS != operatorsChainJS ||
|
|
_expectedClsNameJS != expectedClsNameJS ||
|
|
_clsNameJS != clsNameJS ||
|
|
_clsChainJS != clsChainJS
|
|
) {
|
|
changeBlockState();
|
|
}
|
|
|
|
// save current block data
|
|
blockData->isNewBlock = false;
|
|
blockData->state = state;
|
|
blockData->prevState = prevState;
|
|
blockData->prevPrevState = prevPrevState;
|
|
blockData->mode = QString::fromStdString(mode);
|
|
blockData->prevMode = QString::fromStdString(prevMode);
|
|
blockData->modeExpect = QString::fromStdString(modeExpect);
|
|
blockData->modeExpectC = QString::fromStdString(modeExpectC);
|
|
blockData->modeString = modeString;
|
|
blockData->modeStringC = modeStringC;
|
|
blockData->prevModeExpect = QString::fromStdString(prevModeExpect);
|
|
blockData->prevModeString = prevModeString;
|
|
blockData->prevModeExpectC = QString::fromStdString(prevModeExpectC);
|
|
blockData->prevModeStringC = prevModeStringC;
|
|
blockData->prevModeSkip = prevModeSkip;
|
|
blockData->prevModeSkipC = prevModeSkipC;
|
|
blockData->stringBlock = stringBlock;
|
|
blockData->stringEscStringCSS = stringEscStringCSS;
|
|
blockData->stringEscStringJS = stringEscStringJS;
|
|
blockData->regexpEscStringJS = regexpEscStringJS;
|
|
blockData->regexpPrevCharJS = regexpPrevCharJS;
|
|
blockData->bracesCSS = bracesCSS;
|
|
blockData->bracesJS = bracesJS;
|
|
blockData->bracesPHP = bracesPHP;
|
|
blockData->parensCSS = parensCSS;
|
|
blockData->parensJS = parensJS;
|
|
blockData->parensPHP = parensPHP;
|
|
blockData->cssMediaScope = cssMediaScope;
|
|
blockData->keywordPHPScoped = keywordPHPScoped;
|
|
blockData->keywordJSScoped = keywordJSScoped;
|
|
blockData->exprEscStringJS = exprEscStringJS;
|
|
blockData->stringEscVariableJS = stringEscVariableJS;
|
|
blockData->specialChars = specialChars;
|
|
blockData->specialCharsPos = specialCharsPos;
|
|
blockData->specialWords = specialWords;
|
|
blockData->specialWordsPos = specialWordsPos;
|
|
blockData->modeStarts = modeStarts;
|
|
blockData->modeEnds = modeEnds;
|
|
blockData->modeTags = modeTags;
|
|
blockData->stateStarts = stateStarts;
|
|
blockData->stateEnds = stateEnds;
|
|
blockData->stateIds = stateIds;
|
|
blockData->hasMarkPoint = _hasMarkPoint; // used by editor
|
|
blockData->isModified = _isModified; // used by editor
|
|
blockData->nsNamePHP = nsNamePHP;
|
|
blockData->nsChainPHP = nsChainPHP;
|
|
blockData->nsScopeChainPHP = nsScopeChainPHP;
|
|
blockData->nsStartsPHP = nsStartsPHP;
|
|
blockData->nsEndsPHP = nsEndsPHP;
|
|
blockData->nsNamesPHP = nsNamesPHP;
|
|
blockData->clsNamePHP = clsNamePHP;
|
|
blockData->clsChainPHP = clsChainPHP;
|
|
blockData->clsScopeChainPHP = clsScopeChainPHP;
|
|
blockData->clsStartsPHP = clsStartsPHP;
|
|
blockData->clsEndsPHP = clsEndsPHP;
|
|
blockData->clsNamesPHP = clsNamesPHP;
|
|
blockData->funcNamePHP = funcNamePHP;
|
|
blockData->funcChainPHP = funcChainPHP;
|
|
blockData->funcScopeChainPHP = funcScopeChainPHP;
|
|
blockData->funcStartsPHP = funcStartsPHP;
|
|
blockData->funcEndsPHP = funcEndsPHP;
|
|
blockData->funcNamesPHP = funcNamesPHP;
|
|
blockData->expectedNsNamePHP = expectedNsNamePHP;
|
|
blockData->expectedClsNamePHP = expectedClsNamePHP;
|
|
blockData->expectedFuncNamePHP = expectedFuncNamePHP;
|
|
blockData->expectedFuncParsPHP = expectedFuncParsPHP;
|
|
blockData->expectedFuncArgsPHP = expectedFuncArgsPHP;
|
|
blockData->expectedFuncArgsPHPPositions = expectedFuncArgsPHPPositions;
|
|
blockData->expectedFuncArgsPHPBlocks = expectedFuncArgsPHPBlocks;
|
|
blockData->nsScopePHP = nsScopePHP;
|
|
blockData->clsScopePHP = clsScopePHP;
|
|
blockData->funcScopePHP = funcScopePHP;
|
|
blockData->varsChainsPHP = varsChainsPHP;
|
|
blockData->usedVarsChainsPHP = usedVarsChainsPHP;
|
|
blockData->varsGlobChainPHP = varsGlobChainPHP;
|
|
blockData->usedVarsGlobChainPHP = usedVarsGlobChainPHP;
|
|
blockData->varsClsChainPHP = varsClsChainPHP;
|
|
blockData->varsChainPHP = varsChainPHP;
|
|
blockData->usedVarsChainPHP = usedVarsChainPHP;
|
|
blockData->clsOpenPHP = clsOpenPHP;
|
|
blockData->clsOpensPHP = clsOpensPHP;
|
|
blockData->varsClsOpenChainPHP = varsClsOpenChainPHP;
|
|
blockData->clsPropsChainPHP = clsPropsChainPHP;
|
|
blockData->isGlobalPHP = isGlobalPHP;
|
|
blockData->funcNameJS = funcNameJS;
|
|
blockData->funcScopeChainJS = funcScopeChainJS;
|
|
blockData->funcChainJS = funcChainJS;
|
|
blockData->funcStartsJS= funcStartsJS;
|
|
blockData->funcEndsJS = funcEndsJS;
|
|
blockData->funcNamesJS = funcNamesJS;
|
|
blockData->expectedFuncArgsJS = expectedFuncArgsJS;
|
|
blockData->expectedFuncNameJS = expectedFuncNameJS;
|
|
blockData->expectedFuncVarJS = expectedFuncVarJS;
|
|
blockData->expectedFuncParsJS = expectedFuncParsJS;
|
|
blockData->funcScopeJS = funcScopeJS;
|
|
blockData->varsChainJS = varsChainJS;
|
|
blockData->mediaNameCSS = mediaNameCSS;
|
|
blockData->mediaStartsCSS = mediaStartsCSS;
|
|
blockData->mediaEndsCSS = mediaEndsCSS;
|
|
blockData->mediaNamesCSS = mediaNamesCSS;
|
|
blockData->expectedMediaNameCSS = expectedMediaNameCSS;
|
|
blockData->expectedMediaParsCSS = expectedMediaParsCSS;
|
|
blockData->mediaScopeCSS = mediaScopeCSS;
|
|
blockData->tagChainHTML = tagChainHTML;
|
|
blockData->tagChainStartsHTML = tagChainStartsHTML;
|
|
blockData->tagChainEndsHTML = tagChainEndsHTML;
|
|
blockData->tagChainsHTML = tagChainsHTML;
|
|
blockData->keywordPHPprevString = keywordPHPprevString;
|
|
blockData->keywordPHPprevStringPrevChar = keywordPHPprevStringPrevChar;
|
|
blockData->keywordJSprevString = keywordJSprevString;
|
|
blockData->keywordJSprevStringPrevChar = keywordJSprevStringPrevChar;
|
|
blockData->cssNamesChain = cssNamesChain;
|
|
blockData->operatorsChainPHP = operatorsChainPHP;
|
|
blockData->operatorsPHP = operatorsPHP;
|
|
blockData->operatorsChainJS = operatorsChainJS;
|
|
blockData->operatorsJS = operatorsJS;
|
|
blockData->expectedClsNameJS = expectedClsNameJS;
|
|
blockData->clsNameJS = clsNameJS;
|
|
blockData->clsScopeJS = clsScopeJS;
|
|
blockData->clsChainJS = clsChainJS;
|
|
blockData->clsNamesJS = clsNamesJS;
|
|
blockData->clsStartsJS = clsStartsJS;
|
|
blockData->clsEndsJS = clsEndsJS;
|
|
blockData->clsScopeChainJS = clsScopeChainJS;
|
|
blockData->clsOpensJS = clsOpensJS;
|
|
blockData->clsOpenJS = clsOpenJS;
|
|
cBlock.setUserData(blockData);
|
|
|
|
return true;
|
|
}
|