QSyntaxHighlighter和多行注释

3

我使用Qt的QSyntaxHighlighter来为QML的TextEdit中的某些类C语法着色。

除了多行注释以外,一切都很好。

我是通过以下方式检测它们的:

void highlightBlock(QString const& text) override {
    bool inMultilineComment = previousBlockState() == STATES::COMMENT;
    bool inSingleLineComment = false;
    int previousIndex = 0;

    QRegularExpression expr("(\\/\\*|\\*\\/|\\/\\/|\n)"); // will match either /**, /**, // or \n
    QRegularExpressionMatchIterator it = expr.globalMatch(text);

    while(it.hasNext()) {
        QRegularExpressionMatch match = it.next();

        const QString captured = match.captured(1);

        if(captured == "/*" && !inSingleLineComment) {
            inMultilineComment = true;
            previousIndex = match.capturedStart(1);
        }

        if(captured == "*/" && inMultilineComment) {
            inMultilineComment = false;
            setFormat(previousIndex, match.capturedEnd(1) - previousIndex, _commentFormat);
        }

        if(captured == "//" && !inMultilineComment) {
            inSingleLineComment = true;
        }

        if(captured == "\n" && inSingleLineComment) {
            inSingleLineComment = false;
        }
    }

    if(inMultilineComment) {
        setFormat(previousIndex, text.size() - previousIndex, _commentFormat);
        setCurrentBlockState(STATES::COMMENT);
    }
    else {
        setCurrentBlockState(STATES::NONE);
    }
}

当我删除已经着色的多行注释中的/*时,它可以正常工作。只有包含/*的块被处理和重新上色,但是后面的块没有被处理,这意味着它们在未被注释时仍然出现为注释。

有没有一种简单的方法告诉QSyntaxHighlighter重新处理以下块以防止这种错误的着色?

1个回答

1
我最近遇到了同样的问题,发现Qt实际上应该为您处理此问题,假设您正确设置了blockState。
如果您查看Qt5源代码中的QSyntaxHighlighterPrivate :: reformatBlocks的sourceCode,您会发现
while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) {
    const int stateBeforeHighlight = block.userState();
    reformatBlock(block);
    forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight);
    block = block.next();
}

https://code.woboq.org/qt5/qtbase/src/gui/text/qsyntaxhighlighter.cpp.html#165检索而来的代码

该代码(由QTextDocument发出的contentsChange信号触发)将迭代从刚刚修改的块(行)开始的每个块(行)。假设块的状态基于刚刚发生的键入更改而改变,它将继续处理以下块。这意味着您需要为每一行获取正确的userState,Qt应该处理其余部分。

给出示例:

    /*
     * This is a comment
     *
     * That I made
     */

你需要从每一行都设置了STATES::COMMENT的状态开始,除了最后一行应该设置为STATES::NONE。一旦你做了像删除初始的/*这样的事情,你需要确保块状态被重置为STATES::NONE。这将触发Qt重新运行下一个块,它也需要改变它的状态等等。
在我的(Python)代码中,我最终使用了一些打印语句和真正的调试来跟踪状态更改的传播,并找出了更新不正确并打破更新链的位置。你的代码看起来表面上是正确的,尽管我没有尝试编译和运行它,但我怀疑在编辑后有一些情况会触发状态未正确更新。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接