static void findGrammaticalErrors(TextCheckerClient& client, StringView text, Vector<TextCheckingResult>& results)
{
    for (unsigned checkLocation = 0; checkLocation < text.length(); ) {
        int badGrammarLocation = -1;
        int badGrammarLength = 0;
        Vector<GrammarDetail> badGrammarDetails;
        client.checkGrammarOfString(text.substring(checkLocation), badGrammarDetails, &badGrammarLocation, &badGrammarLength);
        if (!badGrammarLength)
            break;

        ASSERT(badGrammarLocation >= 0);
        ASSERT(static_cast<unsigned>(badGrammarLocation) <= text.length() - checkLocation);
        ASSERT(badGrammarLength > 0);
        ASSERT(static_cast<unsigned>(badGrammarLength) <= text.length() - checkLocation - badGrammarLocation);

        TextCheckingResult badGrammar;
        badGrammar.type = TextCheckingTypeGrammar;
        badGrammar.location = checkLocation + badGrammarLocation;
        badGrammar.length = badGrammarLength;
        badGrammar.details = WTFMove(badGrammarDetails);
        results.append(badGrammar);

        checkLocation += badGrammarLocation + badGrammarLength;
    }
}
예제 #2
0
// https://wicg.github.io/entries-api/#valid-path
static bool isValidVirtualPath(StringView virtualPath)
{
    if (virtualPath.isEmpty())
        return true;
    if (virtualPath[0] == '/') {
        // An absolute path is a string consisting of '/' (U+002F SOLIDUS) followed by one or more path segments joined by '/' (U+002F SOLIDUS).
        return isZeroOrMorePathSegmentsSeparatedBySlashes(virtualPath.substring(1));
    }
    return isValidRelativeVirtualPath(virtualPath);
}
예제 #3
0
Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, StringView text, int32_t insertionPoint, uint64_t checkingTypes, bool)
{
    UNUSED_PARAM(insertionPoint);

    Vector<TextCheckingResult> paragraphCheckingResult;
#if ENABLE(SPELLCHECK)
    if (checkingTypes & TextCheckingTypeSpelling) {
        TextBreakIterator* textIterator = wordBreakIterator(text);
        if (!textIterator)
            return paragraphCheckingResult;

        // Omit the word separators at the beginning/end of the text to don't unnecessarily
        // involve the client to check spelling for them.
        unsigned offset = nextWordOffset(text, 0);
        unsigned lengthStrip = text.length();
        while (lengthStrip > 0 && isTextBreak(textIterator, lengthStrip - 1))
            --lengthStrip;

        while (offset < lengthStrip) {
            int32_t misspellingLocation = -1;
            int32_t misspellingLength = 0;
            checkSpellingOfString(spellDocumentTag, text.substring(offset, lengthStrip - offset), misspellingLocation, misspellingLength);
            if (!misspellingLength)
                break;

            TextCheckingResult misspellingResult;
            misspellingResult.type = TextCheckingTypeSpelling;
            misspellingResult.location = offset + misspellingLocation;
            misspellingResult.length = misspellingLength;
            paragraphCheckingResult.append(misspellingResult);
            offset += misspellingLocation + misspellingLength;
            // Generally, we end up checking at the word separator, move to the adjacent word.
            offset = nextWordOffset(text.substring(0, lengthStrip), offset);
        }
    }
#else
    UNUSED_PARAM(spellDocumentTag);
    UNUSED_PARAM(text);
    UNUSED_PARAM(insertionPoint);
    UNUSED_PARAM(checkingTypes);
#endif
    return paragraphCheckingResult;
}
예제 #4
0
String TextCheckingHelper::findFirstMisspelling(int& firstMisspellingOffset, bool markAll, RefPtr<Range>& firstMisspellingRange)
{
    WordAwareIterator it(*m_range);
    firstMisspellingOffset = 0;
    
    String firstMisspelling;
    int currentChunkOffset = 0;

    while (!it.atEnd()) {
        StringView text = it.text();
        int textLength = text.length();

        // Skip some work for one-space-char hunks
        if (textLength == 1 && text[0] == ' ') {
            int misspellingLocation = -1;
            int misspellingLength = 0;
            m_client->textChecker()->checkSpellingOfString(text, &misspellingLocation, &misspellingLength);

            // 5490627 shows that there was some code path here where the String constructor below crashes.
            // We don't know exactly what combination of bad input caused this, so we're making this much
            // more robust against bad input on release builds.
            ASSERT(misspellingLength >= 0);
            ASSERT(misspellingLocation >= -1);
            ASSERT(!misspellingLength || misspellingLocation >= 0);
            ASSERT(misspellingLocation < textLength);
            ASSERT(misspellingLength <= textLength);
            ASSERT(misspellingLocation + misspellingLength <= textLength);

            if (misspellingLocation >= 0 && misspellingLength > 0 && misspellingLocation < textLength && misspellingLength <= textLength && misspellingLocation + misspellingLength <= textLength) {
                // Compute range of misspelled word
                RefPtr<Range> misspellingRange = TextIterator::subrange(m_range.get(), currentChunkOffset + misspellingLocation, misspellingLength);

                // Remember first-encountered misspelling and its offset.
                if (!firstMisspelling) {
                    firstMisspellingOffset = currentChunkOffset + misspellingLocation;
                    firstMisspelling = text.substring(misspellingLocation, misspellingLength).toString();
                    firstMisspellingRange = misspellingRange;
                }

                // Store marker for misspelled word.
                misspellingRange->startContainer()->document().markers().addMarker(misspellingRange.get(), DocumentMarker::Spelling);

                // Bail out if we're marking only the first misspelling, and not all instances.
                if (!markAll)
                    break;
            }
        }
        
        currentChunkOffset += textLength;
        it.advance();
    }
    
    return firstMisspelling;
}
예제 #5
0
IDBKeyPathLexer::TokenType IDBKeyPathLexer::lex(String& element)
{
    if (m_remainingText.isEmpty())
        return TokenEnd;

    if (m_remainingText[0] == '.') {
        m_remainingText = m_remainingText.substring(1);
        return TokenDot;
    }

    return lexIdentifier(element);
}
예제 #6
0
// https://wicg.github.io/entries-api/#resolve-a-relative-path
static String resolveRelativeVirtualPath(StringView baseVirtualPath, StringView relativeVirtualPath)
{
    ASSERT(baseVirtualPath[0] == '/');
    if (!relativeVirtualPath.isEmpty() && relativeVirtualPath[0] == '/')
        return relativeVirtualPath.length() == 1 ? relativeVirtualPath.toString() : resolveRelativeVirtualPath("/", relativeVirtualPath.substring(1));

    Vector<StringView> virtualPathSegments;
    for (auto segment : baseVirtualPath.split('/'))
        virtualPathSegments.append(segment);

    for (auto segment : relativeVirtualPath.split('/')) {
        ASSERT(!segment.isEmpty());
        if (segment == ".")
            continue;
        if (segment == "..") {
            if (!virtualPathSegments.isEmpty())
                virtualPathSegments.removeLast();
            continue;
        }
        virtualPathSegments.append(segment);
    }

    if (virtualPathSegments.isEmpty())
        return "/"_s;

    StringBuilder builder;
    for (auto& segment : virtualPathSegments) {
        builder.append('/');
        builder.append(segment);
    }
    return builder.toString();
}