Replace TextCheckingTypeMask with OptionSet
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Aug 2018 16:47:43 +0000 (16:47 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Aug 2018 16:47:43 +0000 (16:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=188678

Reviewed by Antti Koivisto.

Source/WebCore:

Replaces TextCheckingTypeMask with an OptionSet to improve type safety and code clarity. Additionally
change the values of TextCheckingType such that all the enumerators fit within an uint8_t.

* PlatformMac.cmake:
* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::hasMisspelling const):
* accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
(AXAttributeStringSetSpelling):
* editing/AlternativeTextController.cpp:
(WebCore::AlternativeTextController::timerFired):
(WebCore::AlternativeTextController::processMarkersOnTextToBeReplacedByResult):
* editing/Editor.cpp:
(WebCore::Editor::replaceSelectionWithFragment):
(WebCore::Editor::markMisspellingsAfterTypingToWord):
(WebCore::Editor::markAllMisspellingsAndBadGrammarInRanges):
(WebCore::isAutomaticTextReplacementType):
(WebCore::Editor::markAndReplaceFor): For now, change a local variable from const to non-const to work
around the following MSVC compiler bug: <https://developercommunity.visualstudio.com/content/problem/316713/msvc-cant-compile-webkits-optionsetcontainsany.html>.
(WebCore::Editor::markMisspellingsAndBadGrammar):
(WebCore::Editor::updateMarkersForWordsAffectedByEditing):
(WebCore::Editor::editorUIUpdateTimerFired):
(WebCore::Editor::resolveTextCheckingTypeMask):
* editing/Editor.h:
* editing/SpellChecker.cpp:
(WebCore::SpellCheckRequest::SpellCheckRequest):
(WebCore::SpellCheckRequest::create):
(WebCore::SpellChecker::didCheckSucceed):
* editing/SpellChecker.h:
* editing/TextCheckingHelper.cpp:
(WebCore::findGrammaticalErrors):
(WebCore::findMisspellings):
(WebCore::TextCheckingHelper::findFirstMisspellingOrBadGrammar):
(WebCore::TextCheckingHelper::guessesForMisspelledOrUngrammaticalRange const):
(WebCore::checkTextOfParagraph):
* editing/TextCheckingHelper.h:
* loader/EmptyClients.cpp:
* platform/text/TextCheckerClient.h:
* platform/text/TextChecking.h: Remove TextCheckingTypeMask. Reorganized the fields of TextCheckingRequestData
to coallesce padding and move it to the end of class. Also used default initializer syntax and defaulted (= default)
the default constructor of TextCheckingRequestData, removing the need for a user-defined default constructor.
(WebCore::TextCheckingRequestData::TextCheckingRequestData):
(WebCore::TextCheckingRequestData::text const): Changed return type from String to const String&
to avoid unnecessary ref-count churn for callers that do not need to take a shared ownership in
this string.
(WebCore::TextCheckingRequestData::checkingTypes const): Renamed; formerly named mask.
(WebCore::TextCheckingRequestData::mask const): Deleted.
* platform/text/mac/TextCheckingMac.mm: Added.
(WebCore::nsTextCheckingTypes):
* testing/Internals.cpp:
(WebCore::Internals::handleAcceptedCandidate):

Source/WebKit:

* Scripts/webkit/messages.py: Add WebCore::TextCheckingType to the special case map so that
the generator knows what header has the definition for this type.
* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<TextCheckingRequestData>::encode):
(IPC::ArgumentCoder<TextCheckingRequestData>::decode):
* UIProcess/Cocoa/WebViewImpl.mm:
(WebKit::coreTextCheckingType):
(WebKit::textCheckingResultFromNSTextCheckingResult):
* UIProcess/TextChecker.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::checkTextOfParagraph):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/gtk/TextCheckerGtk.cpp:
(WebKit::TextChecker::requestCheckingOfString):
(WebKit::TextChecker::checkTextOfParagraph): Also simplified return expressions.
* UIProcess/ios/TextCheckerIOS.mm:
(WebKit::TextChecker::checkTextOfParagraph):
* UIProcess/mac/TextCheckerMac.mm:
(WebKit::TextChecker::checkTextOfParagraph):
* UIProcess/win/TextCheckerWin.cpp:
(WebKit::TextChecker::checkTextOfParagraph):
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::shouldEraseMarkersAfterChangeSelection const):
(WebKit::WebEditorClient::checkTextOfParagraph):
* WebProcess/WebCoreSupport/WebEditorClient.h:

Source/WebKitLegacy/mac:

Currently we have code in WebEditorClient::checkTextOfParagraph() that incorrectly assumes
that the enumerators of TextCheckingType have a one-to-one correspondence with NSTextCheckingType.
(This is not the case because there is not corresponding NSTextCheckingType for TextCheckingTypeShowCorrectionPanel).
We now explicitly convert from OptionSet<TextCheckingType> to NSTextCheckingTypes.

* WebCoreSupport/WebEditorClient.h:
* WebCoreSupport/WebEditorClient.mm:
(WebEditorClient::checkTextOfParagraph):
(WebEditorClient::shouldEraseMarkersAfterChangeSelection const):
(core): Fix up code style nits; compare resultType on the right-hand side instead of the
left as this is more readable and unncessary now that modern compilers like Clang have
diagnostics to catch accidental assignments when equality was intended.
(WebEditorClient::didCheckSucceed):
* WebView/WebView.mm:
(coreTextCheckingType):
(textCheckingResultFromNSTextCheckingResult):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235120 268f45cc-cd09-0410-ab3c-d52691b4dbfc

36 files changed:
Source/WebCore/ChangeLog
Source/WebCore/PlatformMac.cmake
Source/WebCore/SourcesCocoa.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/accessibility/AccessibilityObject.cpp
Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm
Source/WebCore/editing/AlternativeTextController.cpp
Source/WebCore/editing/Editor.cpp
Source/WebCore/editing/Editor.h
Source/WebCore/editing/SpellChecker.cpp
Source/WebCore/editing/SpellChecker.h
Source/WebCore/editing/TextCheckingHelper.cpp
Source/WebCore/editing/TextCheckingHelper.h
Source/WebCore/loader/EmptyClients.cpp
Source/WebCore/platform/text/TextCheckerClient.h
Source/WebCore/platform/text/TextChecking.h
Source/WebCore/platform/text/mac/TextCheckingMac.mm [new file with mode: 0644]
Source/WebCore/testing/Internals.cpp
Source/WebKit/ChangeLog
Source/WebKit/Scripts/webkit/messages.py
Source/WebKit/Shared/WebCoreArgumentCoders.cpp
Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
Source/WebKit/UIProcess/TextChecker.h
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/WebPageProxy.messages.in
Source/WebKit/UIProcess/gtk/TextCheckerGtk.cpp
Source/WebKit/UIProcess/ios/TextCheckerIOS.mm
Source/WebKit/UIProcess/mac/TextCheckerMac.mm
Source/WebKit/UIProcess/win/TextCheckerWin.cpp
Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp
Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h
Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.mm
Source/WebKitLegacy/mac/WebView/WebView.mm

index c41411b..e46193a 100644 (file)
@@ -1,3 +1,63 @@
+2018-08-21  Daniel Bates  <dabates@apple.com>
+
+        Replace TextCheckingTypeMask with OptionSet
+        https://bugs.webkit.org/show_bug.cgi?id=188678
+
+        Reviewed by Antti Koivisto.
+
+        Replaces TextCheckingTypeMask with an OptionSet to improve type safety and code clarity. Additionally
+        change the values of TextCheckingType such that all the enumerators fit within an uint8_t.
+
+        * PlatformMac.cmake:
+        * SourcesCocoa.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::hasMisspelling const):
+        * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
+        (AXAttributeStringSetSpelling):
+        * editing/AlternativeTextController.cpp:
+        (WebCore::AlternativeTextController::timerFired):
+        (WebCore::AlternativeTextController::processMarkersOnTextToBeReplacedByResult):
+        * editing/Editor.cpp:
+        (WebCore::Editor::replaceSelectionWithFragment):
+        (WebCore::Editor::markMisspellingsAfterTypingToWord):
+        (WebCore::Editor::markAllMisspellingsAndBadGrammarInRanges):
+        (WebCore::isAutomaticTextReplacementType):
+        (WebCore::Editor::markAndReplaceFor): For now, change a local variable from const to non-const to work
+        around the following MSVC compiler bug: <https://developercommunity.visualstudio.com/content/problem/316713/msvc-cant-compile-webkits-optionsetcontainsany.html>.
+        (WebCore::Editor::markMisspellingsAndBadGrammar):
+        (WebCore::Editor::updateMarkersForWordsAffectedByEditing):
+        (WebCore::Editor::editorUIUpdateTimerFired):
+        (WebCore::Editor::resolveTextCheckingTypeMask):
+        * editing/Editor.h:
+        * editing/SpellChecker.cpp:
+        (WebCore::SpellCheckRequest::SpellCheckRequest):
+        (WebCore::SpellCheckRequest::create):
+        (WebCore::SpellChecker::didCheckSucceed):
+        * editing/SpellChecker.h:
+        * editing/TextCheckingHelper.cpp:
+        (WebCore::findGrammaticalErrors):
+        (WebCore::findMisspellings):
+        (WebCore::TextCheckingHelper::findFirstMisspellingOrBadGrammar):
+        (WebCore::TextCheckingHelper::guessesForMisspelledOrUngrammaticalRange const):
+        (WebCore::checkTextOfParagraph):
+        * editing/TextCheckingHelper.h:
+        * loader/EmptyClients.cpp:
+        * platform/text/TextCheckerClient.h:
+        * platform/text/TextChecking.h: Remove TextCheckingTypeMask. Reorganized the fields of TextCheckingRequestData
+        to coallesce padding and move it to the end of class. Also used default initializer syntax and defaulted (= default)
+        the default constructor of TextCheckingRequestData, removing the need for a user-defined default constructor.
+        (WebCore::TextCheckingRequestData::TextCheckingRequestData):
+        (WebCore::TextCheckingRequestData::text const): Changed return type from String to const String&
+        to avoid unnecessary ref-count churn for callers that do not need to take a shared ownership in
+        this string.
+        (WebCore::TextCheckingRequestData::checkingTypes const): Renamed; formerly named mask.
+        (WebCore::TextCheckingRequestData::mask const): Deleted.
+        * platform/text/mac/TextCheckingMac.mm: Added.
+        (WebCore::nsTextCheckingTypes):
+        * testing/Internals.cpp:
+        (WebCore::Internals::handleAcceptedCandidate):
+
 2018-08-21  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         Don't place "using namespace XXX;" in global space for unified source builds
index e2f95b4..0d98396 100644 (file)
@@ -452,6 +452,7 @@ list(APPEND WebCore_SOURCES
 
     platform/text/mac/LocaleMac.mm
     platform/text/mac/TextBoundaries.mm
+    platform/text/mac/TextCheckingMac.mm
     platform/text/mac/TextEncodingRegistryMac.mm
 
     rendering/RenderThemeCocoa.mm
index ee9e8b0..66f7f16 100644 (file)
@@ -527,6 +527,7 @@ platform/text/ios/TextEncodingRegistryIOS.mm
 
 platform/text/mac/LocaleMac.mm
 platform/text/mac/TextBoundaries.mm
+platform/text/mac/TextCheckingMac.mm
 platform/text/mac/TextEncodingRegistryMac.mm
 
 rendering/RenderThemeCocoa.mm
index b39dab5..4301656 100644 (file)
                CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextAlternativeWithRange.h; sourceTree = "<group>"; };
                CE7B2DB21586ABAD0098B3FA /* TextAlternativeWithRange.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TextAlternativeWithRange.mm; sourceTree = "<group>"; };
                CE7E17821C83A49100AD06AF /* ContentSecurityPolicyHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicyHash.h; path = csp/ContentSecurityPolicyHash.h; sourceTree = "<group>"; };
+               CEA84720212622AD00940809 /* TextCheckingMac.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TextCheckingMac.mm; sourceTree = "<group>"; };
                CEBB8C3120786DCB00039547 /* FetchIdioms.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FetchIdioms.h; sourceTree = "<group>"; };
                CEBB8C3220786DCB00039547 /* FetchIdioms.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FetchIdioms.cpp; sourceTree = "<group>"; };
                CECADFC2153778FF00E37068 /* DictationAlternative.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DictationAlternative.cpp; sourceTree = "<group>"; };
                                F5973DDE15CFB2030027F804 /* LocaleMac.h */,
                                F5973DDF15CFB2030027F804 /* LocaleMac.mm */,
                                B2AFFC8C0D00A5DF0030074D /* TextBoundaries.mm */,
+                               CEA84720212622AD00940809 /* TextCheckingMac.mm */,
                                A1F55DC41F54D3F000EDB75F /* TextEncodingRegistryMac.mm */,
                        );
                        path = mac;
index 31beacd..f10a151 100644 (file)
@@ -437,7 +437,7 @@ bool AccessibilityObject::hasMisspelling() const
 
     if (unifiedTextCheckerEnabled(frame)) {
         Vector<TextCheckingResult> results;
-        checkTextOfParagraph(*textChecker, stringValue(), TextCheckingTypeSpelling, results, frame->selection().selection());
+        checkTextOfParagraph(*textChecker, stringValue(), TextCheckingType::Spelling, results, frame->selection().selection());
         if (!results.isEmpty())
             isMisspelled = true;
         return isMisspelled;
index e3af278..04c186a 100644 (file)
@@ -909,7 +909,7 @@ static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString,
         
         // checkTextOfParagraph is the only spelling/grammar checker implemented in WK1 and WK2
         Vector<TextCheckingResult> results;
-        checkTextOfParagraph(*checker, text, TextCheckingTypeSpelling, results, node->document().frame()->selection().selection());
+        checkTextOfParagraph(*checker, text, TextCheckingType::Spelling, results, node->document().frame()->selection().selection());
         
         size_t size = results.size();
         for (unsigned i = 0; i < size; i++) {
index 83f83dd..e64f947 100644 (file)
@@ -284,7 +284,7 @@ void AlternativeTextController::timerFired()
         VisiblePosition p = startOfWord(start, LeftWordIfOnBoundary);
         VisibleSelection adjacentWords = VisibleSelection(p, start);
         auto adjacentWordRange = adjacentWords.toNormalizedRange();
-        m_frame.editor().markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeSpelling | TextCheckingTypeReplacement | TextCheckingTypeShowCorrectionPanel, adjacentWordRange.copyRef(), adjacentWordRange.copyRef(), nullptr);
+        m_frame.editor().markAllMisspellingsAndBadGrammarInRanges({ TextCheckingType::Spelling, TextCheckingType::Replacement, TextCheckingType::ShowCorrectionPanel }, adjacentWordRange.copyRef(), adjacentWordRange.copyRef(), nullptr);
     }
         break;
     case AlternativeTextTypeReversion: {
@@ -540,7 +540,7 @@ bool AlternativeTextController::processMarkersOnTextToBeReplacedByResult(const T
 {
     DocumentMarkerController& markerController = m_frame.document()->markers();
     if (markerController.hasMarkers(rangeWithAlternative, DocumentMarker::Replacement)) {
-        if (result.type == TextCheckingTypeCorrection)
+        if (result.type == TextCheckingType::Correction)
             recordSpellcheckerResponseForModifiedCorrection(rangeWithAlternative, stringToBeReplaced, result.replacement);
         return false;
     }
index 1b20d78..bd57eca 100644 (file)
@@ -668,7 +668,7 @@ void Editor::replaceSelectionWithFragment(DocumentFragment& fragment, bool selec
         return;
 
     auto rangeToCheck = Range::create(document(), firstPositionInNode(nodeToCheck), lastPositionInNode(nodeToCheck));
-    if (auto request = SpellCheckRequest::create(resolveTextCheckingTypeMask(*nodeToCheck, TextCheckingTypeSpelling | TextCheckingTypeGrammar), TextCheckingProcessBatch, rangeToCheck.copyRef(), rangeToCheck.copyRef(), rangeToCheck.copyRef()))
+    if (auto request = SpellCheckRequest::create(resolveTextCheckingTypeMask(*nodeToCheck, { TextCheckingType::Spelling, TextCheckingType::Grammar }), TextCheckingProcessBatch, rangeToCheck.copyRef(), rangeToCheck.copyRef(), rangeToCheck.copyRef()))
         m_spellChecker->requestCheckingFor(request.releaseNonNull());
 }
 
@@ -2341,10 +2341,10 @@ void Editor::markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart,
 #if PLATFORM(IOS)
     UNUSED_PARAM(selectionAfterTyping);
     UNUSED_PARAM(doReplacement);
-    TextCheckingTypeMask textCheckingOptions = 0;
+    OptionSet<TextCheckingType> textCheckingOptions;
     if (isContinuousSpellCheckingEnabled())
-        textCheckingOptions |= TextCheckingTypeSpelling;
-    if (!(textCheckingOptions & TextCheckingTypeSpelling))
+        textCheckingOptions |= TextCheckingType::Spelling;
+    if (!textCheckingOptions.contains(TextCheckingType::Spelling))
         return;
 
     VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary));
@@ -2358,10 +2358,10 @@ void Editor::markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart,
     if (unifiedTextCheckerEnabled()) {
         m_alternativeTextController->applyPendingCorrection(selectionAfterTyping);
 
-        TextCheckingTypeMask textCheckingOptions = 0;
+        OptionSet<TextCheckingType> textCheckingOptions;
 
         if (isContinuousSpellCheckingEnabled())
-            textCheckingOptions |= TextCheckingTypeSpelling;
+            textCheckingOptions |= TextCheckingType::Spelling;
 
 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
         if (doReplacement
@@ -2369,14 +2369,14 @@ void Editor::markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart,
                 || isAutomaticLinkDetectionEnabled()
                 || isAutomaticDashSubstitutionEnabled()
                 || isAutomaticTextReplacementEnabled()
-                || ((textCheckingOptions & TextCheckingTypeSpelling) && isAutomaticSpellingCorrectionEnabled())))
-            textCheckingOptions |= TextCheckingTypeReplacement;
+                || (textCheckingOptions.contains(TextCheckingType::Spelling) && isAutomaticSpellingCorrectionEnabled())))
+            textCheckingOptions |= TextCheckingType::Replacement;
 #endif
-        if (!(textCheckingOptions & (TextCheckingTypeSpelling | TextCheckingTypeReplacement)))
+        if (!textCheckingOptions.contains(TextCheckingType::Spelling) && !textCheckingOptions.contains(TextCheckingType::Replacement))
             return;
 
         if (isGrammarCheckingEnabled())
-            textCheckingOptions |= TextCheckingTypeGrammar;
+            textCheckingOptions |= TextCheckingType::Grammar;
 
         auto sentenceStart = startOfSentence(wordStart);
         auto sentenceEnd = endOfSentence(wordStart);
@@ -2558,15 +2558,15 @@ void Editor::markBadGrammar(const VisibleSelection& selection)
 #endif
 }
 
-void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textCheckingOptions, RefPtr<Range>&& spellingRange, RefPtr<Range>&& automaticReplacementRange, RefPtr<Range>&& grammarRange)
+void Editor::markAllMisspellingsAndBadGrammarInRanges(OptionSet<TextCheckingType> textCheckingOptions, RefPtr<Range>&& spellingRange, RefPtr<Range>&& automaticReplacementRange, RefPtr<Range>&& grammarRange)
 {
     ASSERT(unifiedTextCheckerEnabled());
 
     // There shouldn't be pending autocorrection at this moment.
     ASSERT(!m_alternativeTextController->hasPendingCorrection());
 
-    bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar;
-    bool shouldShowCorrectionPanel = textCheckingOptions & TextCheckingTypeShowCorrectionPanel;
+    bool shouldMarkGrammar = textCheckingOptions.contains(TextCheckingType::Grammar);
+    bool shouldShowCorrectionPanel = textCheckingOptions.contains(TextCheckingType::ShowCorrectionPanel);
 
     // This function is called with selections already expanded to word boundaries.
     if (!client() || !spellingRange || (shouldMarkGrammar && !grammarRange))
@@ -2607,16 +2607,16 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textC
 static bool isAutomaticTextReplacementType(TextCheckingType type)
 {
     switch (type) {
-    case TextCheckingTypeNone:
-    case TextCheckingTypeSpelling:
-    case TextCheckingTypeGrammar:
+    case TextCheckingType::None:
+    case TextCheckingType::Spelling:
+    case TextCheckingType::Grammar:
         return false;
-    case TextCheckingTypeLink:
-    case TextCheckingTypeQuote:
-    case TextCheckingTypeDash:
-    case TextCheckingTypeReplacement:
-    case TextCheckingTypeCorrection:
-    case TextCheckingTypeShowCorrectionPanel:
+    case TextCheckingType::Link:
+    case TextCheckingType::Quote:
+    case TextCheckingType::Dash:
+    case TextCheckingType::Replacement:
+    case TextCheckingType::Correction:
+    case TextCheckingType::ShowCorrectionPanel:
         return true;
     }
     ASSERT_NOT_REACHED();
@@ -2646,15 +2646,16 @@ void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<Te
 {
     Ref<Frame> protection(m_frame);
 
-    TextCheckingTypeMask textCheckingOptions = request.data().mask();
+    auto textCheckingOptions = request.data().checkingTypes();
     TextCheckingParagraph paragraph(request.checkingRange(), request.automaticReplacementRange(), &request.paragraphRange());
 
-    const bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling;
-    const bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar;
-    const bool shouldMarkLink = textCheckingOptions & TextCheckingTypeLink;
-    const bool shouldPerformReplacement = textCheckingOptions & (TextCheckingTypeQuote | TextCheckingTypeDash | TextCheckingTypeReplacement);
-    const bool shouldShowCorrectionPanel = textCheckingOptions & TextCheckingTypeShowCorrectionPanel;
-    const bool shouldCheckForCorrection = shouldShowCorrectionPanel || (textCheckingOptions & TextCheckingTypeCorrection);
+    // FIXME: Mark this const once MSVC bug is fixed: <https://developercommunity.visualstudio.com/content/problem/316713/msvc-cant-compile-webkits-optionsetcontainsany.html>.
+    bool shouldPerformReplacement = textCheckingOptions.containsAny({ TextCheckingType::Quote, TextCheckingType::Dash, TextCheckingType::Replacement });
+    const bool shouldMarkSpelling = textCheckingOptions.contains(TextCheckingType::Spelling);
+    const bool shouldMarkGrammar = textCheckingOptions.contains(TextCheckingType::Grammar);
+    const bool shouldMarkLink = textCheckingOptions.contains(TextCheckingType::Link);
+    const bool shouldShowCorrectionPanel = textCheckingOptions.contains(TextCheckingType::ShowCorrectionPanel);
+    const bool shouldCheckForCorrection = shouldShowCorrectionPanel || textCheckingOptions.contains(TextCheckingType::Correction);
 #if !USE(AUTOCORRECTION_PANEL)
     ASSERT(!shouldShowCorrectionPanel);
 #endif
@@ -2696,14 +2697,14 @@ void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<Te
         // 2. Result falls within spellingRange.
         // 3. The word in question doesn't end at an ambiguous boundary. For instance, we would not mark
         //    "wouldn'" as misspelled right after apostrophe is typed.
-        if (shouldMarkSpelling && !shouldShowCorrectionPanel && resultType == TextCheckingTypeSpelling
+        if (shouldMarkSpelling && !shouldShowCorrectionPanel && resultType == TextCheckingType::Spelling
             && resultLocation >= paragraph.checkingStart() && resultEndLocation <= spellingRangeEndOffset && !resultEndsAtAmbiguousBoundary) {
             ASSERT(resultLength > 0 && resultLocation >= 0);
             auto misspellingRange = paragraph.subrange(resultLocation, resultLength);
             if (!m_alternativeTextController->isSpellingMarkerAllowed(misspellingRange))
                 continue;
             misspellingRange->startContainer().document().markers().addMarker(misspellingRange.ptr(), DocumentMarker::Spelling, replacement);
-        } else if (shouldMarkGrammar && resultType == TextCheckingTypeGrammar && paragraph.checkingRangeCovers(resultLocation, resultLength)) {
+        } else if (shouldMarkGrammar && resultType == TextCheckingType::Grammar && paragraph.checkingRangeCovers(resultLocation, resultLength)) {
             ASSERT(resultLength > 0 && resultLocation >= 0);
             for (auto& detail : results[i].details) {
                 ASSERT(detail.length > 0 && detail.location >= 0);
@@ -2718,7 +2719,7 @@ void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<Te
             ASSERT(resultLength > 0 && resultLocation >= 0);
 
             if (shouldShowCorrectionPanel && (resultEndLocation < automaticReplacementEndLocation
-                || !(resultType & (TextCheckingTypeReplacement | TextCheckingTypeCorrection))))
+                || (resultType != TextCheckingType::Replacement && resultType != TextCheckingType::Correction)))
                 continue;
 
             // Apply replacement if:
@@ -2728,8 +2729,8 @@ void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<Te
             bool doReplacement = replacement.length() > 0 && !resultEndsAtAmbiguousBoundary;
             auto rangeToReplace = paragraph.subrange(resultLocation, resultLength);
 
-            // adding links should be done only immediately after they are typed
-            if (resultType == TextCheckingTypeLink && selectionOffset != resultEndLocation + 1)
+            // Adding links should be done only immediately after they are typed.
+            if (resultType == TextCheckingType::Link && selectionOffset != resultEndLocation + 1)
                 continue;
 
             if (!(shouldPerformReplacement || shouldCheckForCorrection || shouldMarkLink) || !doReplacement)
@@ -2756,7 +2757,7 @@ void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<Te
                     continue;
             }
 
-            if (resultType == TextCheckingTypeLink) {
+            if (resultType == TextCheckingType::Link) {
                 m_frame.selection().setSelection(selectionToReplace);
                 selectionChanged = true;
                 restoreSelectionAfterChange = false;
@@ -2779,7 +2780,7 @@ void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<Te
                 if (resultLocation < selectionOffset)
                     selectionOffset += replacement.length() - resultLength;
 
-                if (resultType == TextCheckingTypeCorrection) {
+                if (resultType == TextCheckingType::Correction) {
                     auto replacementRange = paragraph.subrange(resultLocation, replacement.length());
                     m_alternativeTextController->recordAutocorrectionResponse(AutocorrectionResponse::Accepted, replacedString, replacementRange.ptr());
 
@@ -2839,9 +2840,9 @@ void Editor::markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelec
             return;
 
         // markMisspellingsAndBadGrammar() is triggered by selection change, in which case we check spelling and grammar, but don't autocorrect misspellings.
-        TextCheckingTypeMask textCheckingOptions = TextCheckingTypeSpelling;
+        OptionSet<TextCheckingType> textCheckingOptions { TextCheckingType::Spelling };
         if (markGrammar && isGrammarCheckingEnabled())
-            textCheckingOptions |= TextCheckingTypeGrammar;
+            textCheckingOptions |= TextCheckingType::Grammar;
         auto spellCheckingRange = spellingSelection.toNormalizedRange();
         markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, spellCheckingRange.copyRef(), spellCheckingRange.copyRef(), grammarSelection.toNormalizedRange());
         return;
@@ -2863,7 +2864,7 @@ void Editor::updateMarkersForWordsAffectedByEditing(bool doNotRemoveIfSelectionA
     if (!document().markers().hasMarkers())
         return;
 
-    if (!m_alternativeTextController->shouldRemoveMarkersUponEditing() && (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeSpelling)))
+    if (!m_alternativeTextController->shouldRemoveMarkersUponEditing() && (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingType::Spelling)))
         return;
 
     // We want to remove the markers from a word if an editing command will change the word. This can happen in one of
@@ -3654,11 +3655,11 @@ void Editor::editorUIUpdateTimerFired()
             }
         }
 
-        if (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeSpelling)) {
+        if (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingType::Spelling)) {
             if (RefPtr<Range> wordRange = newAdjacentWords.toNormalizedRange())
                 document().markers().removeMarkers(wordRange.get(), DocumentMarker::Spelling);
         }
-        if (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeGrammar)) {
+        if (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingType::Grammar)) {
             if (RefPtr<Range> sentenceRange = newSelectedSentence.toNormalizedRange())
                 document().markers().removeMarkers(sentenceRange.get(), DocumentMarker::Grammar);
         }
@@ -3715,51 +3716,51 @@ bool Editor::selectionStartHasMarkerFor(DocumentMarker::MarkerType markerType, i
     return false;
 }       
 
-TextCheckingTypeMask Editor::resolveTextCheckingTypeMask(const Node& rootEditableElement, TextCheckingTypeMask textCheckingOptions)
+OptionSet<TextCheckingType> Editor::resolveTextCheckingTypeMask(const Node& rootEditableElement, OptionSet<TextCheckingType> textCheckingOptions)
 {
 #if USE(AUTOMATIC_TEXT_REPLACEMENT) && !PLATFORM(IOS)
     bool onlyAllowsTextReplacement = false;
     if (auto* host = rootEditableElement.shadowHost())
         onlyAllowsTextReplacement = is<HTMLInputElement>(host) && downcast<HTMLInputElement>(*host).isSpellcheckDisabledExceptTextReplacement();
     if (onlyAllowsTextReplacement)
-        textCheckingOptions &= TextCheckingTypeReplacement;
+        textCheckingOptions = textCheckingOptions & TextCheckingType::Replacement;
 #else
     UNUSED_PARAM(rootEditableElement);
 #endif
 
-    bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling;
-    bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar;
+    bool shouldMarkSpelling = textCheckingOptions.contains(TextCheckingType::Spelling);
+    bool shouldMarkGrammar = textCheckingOptions.contains(TextCheckingType::Grammar);
 #if !PLATFORM(IOS)
-    bool shouldShowCorrectionPanel = textCheckingOptions & TextCheckingTypeShowCorrectionPanel;
-    bool shouldCheckForCorrection = shouldShowCorrectionPanel || (textCheckingOptions & TextCheckingTypeCorrection);
+    bool shouldShowCorrectionPanel = textCheckingOptions.contains(TextCheckingType::ShowCorrectionPanel);
+    bool shouldCheckForCorrection = shouldShowCorrectionPanel || textCheckingOptions.contains(TextCheckingType::Correction);
 #endif
 
-    TextCheckingTypeMask checkingTypes = 0;
+    OptionSet<TextCheckingType> checkingTypes;
     if (shouldMarkSpelling)
-        checkingTypes |= TextCheckingTypeSpelling;
+        checkingTypes |= TextCheckingType::Spelling;
     if (shouldMarkGrammar)
-        checkingTypes |= TextCheckingTypeGrammar;
+        checkingTypes |= TextCheckingType::Grammar;
 #if !PLATFORM(IOS)
     if (shouldCheckForCorrection)
-        checkingTypes |= TextCheckingTypeCorrection;
+        checkingTypes |= TextCheckingType::Correction;
     if (shouldShowCorrectionPanel)
-        checkingTypes |= TextCheckingTypeShowCorrectionPanel;
+        checkingTypes |= TextCheckingType::ShowCorrectionPanel;
 
 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
-    bool shouldPerformReplacement = textCheckingOptions & TextCheckingTypeReplacement;
+    bool shouldPerformReplacement = textCheckingOptions.contains(TextCheckingType::Replacement);
     if (shouldPerformReplacement) {
         if (!onlyAllowsTextReplacement) {
             if (isAutomaticLinkDetectionEnabled())
-                checkingTypes |= TextCheckingTypeLink;
+                checkingTypes |= TextCheckingType::Link;
             if (isAutomaticQuoteSubstitutionEnabled())
-                checkingTypes |= TextCheckingTypeQuote;
+                checkingTypes |= TextCheckingType::Quote;
             if (isAutomaticDashSubstitutionEnabled())
-                checkingTypes |= TextCheckingTypeDash;
+                checkingTypes |= TextCheckingType::Dash;
             if (shouldMarkSpelling && isAutomaticSpellingCorrectionEnabled())
-                checkingTypes |= TextCheckingTypeCorrection;
+                checkingTypes |= TextCheckingType::Correction;
         }
         if (isAutomaticTextReplacementEnabled())
-            checkingTypes |= TextCheckingTypeReplacement;
+            checkingTypes |= TextCheckingType::Replacement;
     }
 #endif
 #endif // !PLATFORM(IOS)
index 8ad7882..b237795 100644 (file)
@@ -289,7 +289,7 @@ public:
     bool isOverwriteModeEnabled() const { return m_overwriteModeEnabled; }
     WEBCORE_EXPORT void toggleOverwriteModeEnabled();
 
-    void markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask, RefPtr<Range>&& spellingRange, RefPtr<Range>&& automaticReplacementRange, RefPtr<Range>&& grammarRange);
+    void markAllMisspellingsAndBadGrammarInRanges(OptionSet<TextCheckingType>, RefPtr<Range>&& spellingRange, RefPtr<Range>&& automaticReplacementRange, RefPtr<Range>&& grammarRange);
 #if PLATFORM(IOS)
     NO_RETURN_DUE_TO_ASSERT
 #endif
@@ -528,7 +528,7 @@ private:
 
     void revealSelectionAfterEditingOperation(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, RevealExtentOption = DoNotRevealExtent);
     void markMisspellingsOrBadGrammar(const VisibleSelection&, bool checkSpelling, RefPtr<Range>& firstMisspellingRange);
-    TextCheckingTypeMask resolveTextCheckingTypeMask(const Node& rootEditableElement, TextCheckingTypeMask);
+    OptionSet<TextCheckingType> resolveTextCheckingTypeMask(const Node& rootEditableElement, OptionSet<TextCheckingType>);
 
     WEBCORE_EXPORT String selectedText(TextIteratorBehavior) const;
 
index c054c5a..ce1a9ef 100644 (file)
@@ -40,7 +40,7 @@
 
 namespace WebCore {
 
-SpellCheckRequest::SpellCheckRequest(Ref<Range>&& checkingRange, Ref<Range>&& automaticReplacementRange, Ref<Range>&& paragraphRange, const String& text, TextCheckingTypeMask mask, TextCheckingProcessType processType)
+SpellCheckRequest::SpellCheckRequest(Ref<Range>&& checkingRange, Ref<Range>&& automaticReplacementRange, Ref<Range>&& paragraphRange, const String& text, OptionSet<TextCheckingType> mask, TextCheckingProcessType processType)
     : m_checkingRange(WTFMove(checkingRange))
     , m_automaticReplacementRange(WTFMove(automaticReplacementRange))
     , m_paragraphRange(WTFMove(paragraphRange))
@@ -51,7 +51,7 @@ SpellCheckRequest::SpellCheckRequest(Ref<Range>&& checkingRange, Ref<Range>&& au
 
 SpellCheckRequest::~SpellCheckRequest() = default;
 
-RefPtr<SpellCheckRequest> SpellCheckRequest::create(TextCheckingTypeMask textCheckingOptions, TextCheckingProcessType processType, Ref<Range>&& checkingRange, Ref<Range>&& automaticReplacementRange, Ref<Range>&& paragraphRange)
+RefPtr<SpellCheckRequest> SpellCheckRequest::create(OptionSet<TextCheckingType> textCheckingOptions, TextCheckingProcessType processType, Ref<Range>&& checkingRange, Ref<Range>&& automaticReplacementRange, Ref<Range>&& paragraphRange)
 {
     String text = checkingRange->text();
     if (!text.length())
@@ -217,9 +217,9 @@ void SpellChecker::didCheckSucceed(int sequence, const Vector<TextCheckingResult
     TextCheckingRequestData requestData = m_processingRequest->data();
     if (requestData.sequence() == sequence) {
         OptionSet<DocumentMarker::MarkerType> markerTypes;
-        if (requestData.mask() & TextCheckingTypeSpelling)
+        if (requestData.checkingTypes().contains(TextCheckingType::Spelling))
             markerTypes |= DocumentMarker::Spelling;
-        if (requestData.mask() & TextCheckingTypeGrammar)
+        if (requestData.checkingTypes().contains(TextCheckingType::Grammar))
             markerTypes |= DocumentMarker::Grammar;
         if (!markerTypes.isEmpty())
             m_frame.document()->markers().removeMarkers(&m_processingRequest->checkingRange(), markerTypes);
index 0594536..0515c5b 100644 (file)
@@ -44,7 +44,7 @@ class SpellChecker;
 
 class SpellCheckRequest : public TextCheckingRequest {
 public:
-    static RefPtr<SpellCheckRequest> create(TextCheckingTypeMask, TextCheckingProcessType, Ref<Range>&& checkingRange, Ref<Range>&& automaticReplacementRange, Ref<Range>&& paragraphRange);
+    static RefPtr<SpellCheckRequest> create(OptionSet<TextCheckingType>, TextCheckingProcessType, Ref<Range>&& checkingRange, Ref<Range>&& automaticReplacementRange, Ref<Range>&& paragraphRange);
     virtual ~SpellCheckRequest();
 
     Range& checkingRange() const { return m_checkingRange.get(); }
@@ -61,7 +61,7 @@ public:
     void didCancel() override;
 
 private:
-    SpellCheckRequest(Ref<Range>&& checkingRange, Ref<Range>&& automaticReplacementRange, Ref<Range>&& paragraphRange, const String&, TextCheckingTypeMask, TextCheckingProcessType);
+    SpellCheckRequest(Ref<Range>&& checkingRange, Ref<Range>&& automaticReplacementRange, Ref<Range>&& paragraphRange, const String&, OptionSet<TextCheckingType>, TextCheckingProcessType);
 
     SpellChecker* m_checker { nullptr };
     Ref<Range> m_checkingRange;
index d519066..05a6cba 100644 (file)
@@ -62,7 +62,7 @@ static void findGrammaticalErrors(TextCheckerClient& client, StringView text, Ve
         ASSERT(static_cast<unsigned>(badGrammarLength) <= text.length() - checkLocation - badGrammarLocation);
 
         TextCheckingResult badGrammar;
-        badGrammar.type = TextCheckingTypeGrammar;
+        badGrammar.type = TextCheckingType::Grammar;
         badGrammar.location = checkLocation + badGrammarLocation;
         badGrammar.length = badGrammarLength;
         badGrammar.details = WTFMove(badGrammarDetails);
@@ -96,7 +96,7 @@ static void findMisspellings(TextCheckerClient& client, StringView text, Vector<
             ASSERT(misspellingLocation + misspellingLength <= wordLength);
 
             TextCheckingResult misspelling;
-            misspelling.type = TextCheckingTypeSpelling;
+            misspelling.type = TextCheckingType::Spelling;
             misspelling.location = wordStart + misspellingLocation;
             misspelling.length = misspellingLength;
             misspelling.replacement = client.getAutoCorrectSuggestionForMisspelledWord(text.substring(misspelling.location, misspelling.length).toStringWithoutCopying());
@@ -351,14 +351,16 @@ String TextCheckingHelper::findFirstMisspellingOrBadGrammar(bool checkGrammar, b
                 unsigned grammarDetailIndex = 0;
                 
                 Vector<TextCheckingResult> results;
-                TextCheckingTypeMask checkingTypes = checkGrammar ? (TextCheckingTypeSpelling | TextCheckingTypeGrammar) : TextCheckingTypeSpelling;
+                OptionSet<TextCheckingType> checkingTypes { TextCheckingType::Spelling };
+                if (checkGrammar)
+                    checkingTypes |= TextCheckingType::Grammar;
                 VisibleSelection currentSelection;
                 if (Frame* frame = paragraphRange->ownerDocument().frame())
                     currentSelection = frame->selection().selection();
                 checkTextOfParagraph(*m_client.textChecker(), paragraphString, checkingTypes, results, currentSelection);
 
                 for (auto& result : results) {
-                    if (result.type == TextCheckingTypeSpelling && result.location >= currentStartOffset && result.location + result.length <= currentEndOffset) {
+                    if (result.type == TextCheckingType::Spelling && result.location >= currentStartOffset && result.location + result.length <= currentEndOffset) {
                         ASSERT(result.length > 0);
                         ASSERT(result.location >= 0);
                         spellingLocation = result.location;
@@ -366,7 +368,7 @@ String TextCheckingHelper::findFirstMisspellingOrBadGrammar(bool checkGrammar, b
                         ASSERT(misspelledWord.length());
                         break;
                     }
-                    if (checkGrammar && result.type == TextCheckingTypeGrammar && result.location < currentEndOffset && result.location + result.length > currentStartOffset) {
+                    if (checkGrammar && result.type == TextCheckingType::Grammar && result.location < currentEndOffset && result.location + result.length > currentStartOffset) {
                         ASSERT(result.length > 0);
                         ASSERT(result.location >= 0);
                         // We can't stop after the first grammar result, since there might still be a spelling result after
@@ -583,14 +585,16 @@ Vector<String> TextCheckingHelper::guessesForMisspelledOrUngrammaticalRange(bool
         return guesses;
 
     Vector<TextCheckingResult> results;
-    TextCheckingTypeMask checkingTypes = checkGrammar ? (TextCheckingTypeSpelling | TextCheckingTypeGrammar) : TextCheckingTypeSpelling;
+    OptionSet<TextCheckingType> checkingTypes { TextCheckingType::Spelling };
+    if (checkGrammar)
+        checkingTypes |= TextCheckingType::Grammar;
     VisibleSelection currentSelection;
     if (Frame* frame = m_range->ownerDocument().frame())
         currentSelection = frame->selection().selection();
     checkTextOfParagraph(*m_client.textChecker(), paragraph.text(), checkingTypes, results, currentSelection);
 
     for (auto& result : results) {
-        if (result.type == TextCheckingTypeSpelling && paragraph.checkingRangeMatches(result.location, result.length)) {
+        if (result.type == TextCheckingType::Spelling && paragraph.checkingRangeMatches(result.location, result.length)) {
             String misspelledWord = paragraph.checkingSubstring();
             ASSERT(misspelledWord.length());
             m_client.textChecker()->getGuessesForWord(misspelledWord, String(), currentSelection, guesses);
@@ -604,7 +608,7 @@ Vector<String> TextCheckingHelper::guessesForMisspelledOrUngrammaticalRange(bool
         return guesses;
 
     for (auto& result : results) {
-        if (result.type == TextCheckingTypeGrammar && paragraph.isCheckingRangeCoveredBy(result.location, result.length)) {
+        if (result.type == TextCheckingType::Grammar && paragraph.isCheckingRangeCoveredBy(result.location, result.length)) {
             for (auto& detail : result.details) {
                 ASSERT(detail.length > 0);
                 ASSERT(detail.location >= 0);
@@ -647,7 +651,7 @@ bool TextCheckingHelper::unifiedTextCheckerEnabled() const
     return WebCore::unifiedTextCheckerEnabled(m_range->ownerDocument().frame());
 }
 
-void checkTextOfParagraph(TextCheckerClient& client, StringView text, TextCheckingTypeMask checkingTypes, Vector<TextCheckingResult>& results, const VisibleSelection& currentSelection)
+void checkTextOfParagraph(TextCheckerClient& client, StringView text, OptionSet<TextCheckingType> checkingTypes, Vector<TextCheckingResult>& results, const VisibleSelection& currentSelection)
 {
 #if USE(UNIFIED_TEXT_CHECKING)
     results = client.checkTextOfParagraph(text, checkingTypes, currentSelection);
@@ -655,13 +659,13 @@ void checkTextOfParagraph(TextCheckerClient& client, StringView text, TextChecki
     UNUSED_PARAM(currentSelection);
 
     Vector<TextCheckingResult> mispellings;
-    if (checkingTypes & TextCheckingTypeSpelling)
+    if (checkingTypes.contains(TextCheckingType::Spelling))
         findMisspellings(client, text, mispellings);
 
 #if USE(GRAMMAR_CHECKING)
     // Look for grammatical errors that occur before the first misspelling.
     Vector<TextCheckingResult> grammaticalErrors;
-    if (checkingTypes & TextCheckingTypeGrammar) {
+    if (checkingTypes.contains(TextCheckingType::Grammar)) {
         unsigned grammarCheckLength = text.length();
         for (auto& mispelling : mispellings)
             grammarCheckLength = std::min<unsigned>(grammarCheckLength, mispelling.location);
index ce04e40..1e8c9fa 100644 (file)
@@ -108,7 +108,7 @@ private:
 #endif
 };
 
-void checkTextOfParagraph(TextCheckerClient&, StringView, TextCheckingTypeMask, Vector<TextCheckingResult>&, const VisibleSelection& currentSelection);
+void checkTextOfParagraph(TextCheckerClient&, StringView, OptionSet<TextCheckingType>, Vector<TextCheckingResult>&, const VisibleSelection& currentSelection);
 
 bool unifiedTextCheckerEnabled(const Frame*);
 
index 2f2fb08..d4b915d 100644 (file)
@@ -264,7 +264,7 @@ private:
         void checkGrammarOfString(StringView, Vector<GrammarDetail>&, int*, int*) final { }
 
 #if USE(UNIFIED_TEXT_CHECKING)
-        Vector<TextCheckingResult> checkTextOfParagraph(StringView, TextCheckingTypeMask, const VisibleSelection&) final { return Vector<TextCheckingResult>(); }
+        Vector<TextCheckingResult> checkTextOfParagraph(StringView, OptionSet<TextCheckingType>, const VisibleSelection&) final { return Vector<TextCheckingResult>(); }
 #endif
 
         void getGuessesForWord(const String&, const String&, const VisibleSelection&, Vector<String>&) final { }
index 611e97b..e18ed5f 100644 (file)
@@ -45,7 +45,7 @@ public:
     virtual void checkGrammarOfString(StringView, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength) = 0;
 
 #if USE(UNIFIED_TEXT_CHECKING)
-    virtual Vector<TextCheckingResult> checkTextOfParagraph(StringView, TextCheckingTypeMask checkingTypes, const VisibleSelection& currentSelection) = 0;
+    virtual Vector<TextCheckingResult> checkTextOfParagraph(StringView, OptionSet<TextCheckingType> checkingTypes, const VisibleSelection& currentSelection) = 0;
 #endif
 
     // For spellcheckers that support multiple languages, it's often important to be able to identify the language in order to
index 7d58a50..084e7f0 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef TextChecking_h
-#define TextChecking_h
+#pragma once
 
+#include <wtf/OptionSet.h>
 #include <wtf/RefCounted.h>
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
-enum TextCheckingType {
-    TextCheckingTypeNone        = 0,
-    TextCheckingTypeSpelling    = 1 << 1,
-    TextCheckingTypeGrammar     = 1 << 2,
-    TextCheckingTypeLink        = 1 << 5,
-    TextCheckingTypeQuote       = 1 << 6,
-    TextCheckingTypeDash        = 1 << 7,
-    TextCheckingTypeReplacement = 1 << 8,
-    TextCheckingTypeCorrection  = 1 << 9,
-    TextCheckingTypeShowCorrectionPanel = 1 << 10
+enum class TextCheckingType : uint8_t {
+    None = 0,
+    Spelling = 1 << 0,
+    Grammar = 1 << 1,
+    Link = 1 << 2,
+    Quote = 1 << 3,
+    Dash = 1 << 4,
+    Replacement = 1 << 5,
+    Correction = 1 << 6,
+    ShowCorrectionPanel = 1 << 7,
 };
 
-typedef unsigned TextCheckingTypeMask;
+#if PLATFORM(MAC)
+typedef uint64_t NSTextCheckingTypes;
+WEBCORE_EXPORT NSTextCheckingTypes nsTextCheckingTypes(OptionSet<TextCheckingType>);
+#endif
 
 enum TextCheckingProcessType {
     TextCheckingProcessBatch,
@@ -76,28 +80,25 @@ const int unrequestedTextCheckingSequence = -1;
 class TextCheckingRequestData {
     friend class SpellCheckRequest; // For access to m_sequence.
 public:
-    TextCheckingRequestData()
-        : m_sequence(unrequestedTextCheckingSequence)
-        , m_mask(TextCheckingTypeNone)
-        , m_processType(TextCheckingProcessIncremental)
-    { }
-    TextCheckingRequestData(int sequence, const String& text, TextCheckingTypeMask mask, TextCheckingProcessType processType)
-        : m_sequence(sequence)
-        , m_text(text)
-        , m_mask(mask)
-        , m_processType(processType)
-    { }
+    TextCheckingRequestData() = default;
+    TextCheckingRequestData(int sequence, const String& text, OptionSet<TextCheckingType> checkingTypes, TextCheckingProcessType processType)
+        : m_text { text }
+        , m_sequence { sequence }
+        , m_processType { processType }
+        , m_checkingTypes { checkingTypes }
+    {
+    }
 
     int sequence() const { return m_sequence; }
-    String text() const { return m_text; }
-    TextCheckingTypeMask mask() const { return m_mask; }
+    const String& text() const { return m_text; }
+    OptionSet<TextCheckingType> checkingTypes() const { return m_checkingTypes; }
     TextCheckingProcessType processType() const { return m_processType; }
 
 private:
-    int m_sequence;
     String m_text;
-    TextCheckingTypeMask m_mask;
-    TextCheckingProcessType m_processType;
+    int m_sequence { unrequestedTextCheckingSequence };
+    TextCheckingProcessType m_processType { TextCheckingProcessIncremental };
+    OptionSet<TextCheckingType> m_checkingTypes;
 };
 
 class TextCheckingRequest : public RefCounted<TextCheckingRequest> {
@@ -110,5 +111,3 @@ public:
 };
 
 }
-
-#endif // TextChecking_h
diff --git a/Source/WebCore/platform/text/mac/TextCheckingMac.mm b/Source/WebCore/platform/text/mac/TextCheckingMac.mm
new file mode 100644 (file)
index 0000000..b5dc142
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "TextChecking.h"
+
+#if PLATFORM(MAC)
+
+#import <Foundation/Foundation.h>
+
+namespace WebCore {
+
+NSTextCheckingTypes nsTextCheckingTypes(OptionSet<TextCheckingType> types)
+{
+    NSTextCheckingTypes mask = 0;
+    if (types.contains(TextCheckingType::Spelling))
+        mask |= NSTextCheckingTypeSpelling;
+    if (types.contains(TextCheckingType::Grammar))
+        mask |= NSTextCheckingTypeGrammar;
+    if (types.contains(TextCheckingType::Link))
+        mask |= NSTextCheckingTypeLink;
+    if (types.contains(TextCheckingType::Quote))
+        mask |= NSTextCheckingTypeQuote;
+    if (types.contains(TextCheckingType::Dash))
+        mask |= NSTextCheckingTypeDash;
+    if (types.contains(TextCheckingType::Replacement))
+        mask |= NSTextCheckingTypeReplacement;
+    if (types.contains(TextCheckingType::Correction))
+        mask |= NSTextCheckingTypeCorrection;
+    return mask;
+}
+
+} // namespace WebCore
+
+#endif // PLATFORM(MAC)
index 0f37961..efe156f 100644 (file)
@@ -2196,7 +2196,7 @@ void Internals::handleAcceptedCandidate(const String& candidate, unsigned locati
         return;
 
     TextCheckingResult result;
-    result.type = TextCheckingTypeNone;
+    result.type = TextCheckingType::None;
     result.location = location;
     result.length = length;
     result.replacement = candidate;
index 55852dc..5248e3f 100644 (file)
@@ -1,3 +1,37 @@
+2018-08-21  Daniel Bates  <dabates@apple.com>
+
+        Replace TextCheckingTypeMask with OptionSet
+        https://bugs.webkit.org/show_bug.cgi?id=188678
+
+        Reviewed by Antti Koivisto.
+
+        * Scripts/webkit/messages.py: Add WebCore::TextCheckingType to the special case map so that
+        the generator knows what header has the definition for this type.
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<TextCheckingRequestData>::encode):
+        (IPC::ArgumentCoder<TextCheckingRequestData>::decode):
+        * UIProcess/Cocoa/WebViewImpl.mm:
+        (WebKit::coreTextCheckingType):
+        (WebKit::textCheckingResultFromNSTextCheckingResult):
+        * UIProcess/TextChecker.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::checkTextOfParagraph):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/gtk/TextCheckerGtk.cpp:
+        (WebKit::TextChecker::requestCheckingOfString):
+        (WebKit::TextChecker::checkTextOfParagraph): Also simplified return expressions.
+        * UIProcess/ios/TextCheckerIOS.mm:
+        (WebKit::TextChecker::checkTextOfParagraph):
+        * UIProcess/mac/TextCheckerMac.mm:
+        (WebKit::TextChecker::checkTextOfParagraph):
+        * UIProcess/win/TextCheckerWin.cpp:
+        (WebKit::TextChecker::checkTextOfParagraph):
+        * WebProcess/WebCoreSupport/WebEditorClient.cpp:
+        (WebKit::WebEditorClient::shouldEraseMarkersAfterChangeSelection const):
+        (WebKit::WebEditorClient::checkTextOfParagraph):
+        * WebProcess/WebCoreSupport/WebEditorClient.h:
+
 2018-08-21  Adrian Perez de Castro  <aperez@igalia.com>
 
         Unreviewed. Update OptionsWPE.cmake and NEWS for 2.21.91 release.
index 09e464f..95cdc0f 100644 (file)
@@ -414,6 +414,7 @@ def headers_for_type(type):
         'WebCore::SupportedPluginIdentifier': ['<WebCore/PluginData.h>'],
         'WebCore::TextCheckingRequestData': ['<WebCore/TextChecking.h>'],
         'WebCore::TextCheckingResult': ['<WebCore/TextCheckerClient.h>'],
+        'WebCore::TextCheckingType': ['<WebCore/TextChecking.h>'],
         'WebCore::TextIndicatorData': ['<WebCore/TextIndicator.h>'],
         'WebCore::ViewportAttributes': ['<WebCore/ViewportArguments.h>'],
         'WebCore::SelectionRect': ['"EditorState.h"'],
index baa2fcf..5ee415a 100644 (file)
@@ -1956,7 +1956,7 @@ void ArgumentCoder<TextCheckingRequestData>::encode(Encoder& encoder, const Text
 {
     encoder << request.sequence();
     encoder << request.text();
-    encoder << request.mask();
+    encoder << request.checkingTypes();
     encoder.encodeEnum(request.processType());
 }
 
@@ -1970,15 +1970,15 @@ bool ArgumentCoder<TextCheckingRequestData>::decode(Decoder& decoder, TextChecki
     if (!decoder.decode(text))
         return false;
 
-    TextCheckingTypeMask mask;
-    if (!decoder.decode(mask))
+    OptionSet<TextCheckingType> checkingTypes;
+    if (!decoder.decode(checkingTypes))
         return false;
 
     TextCheckingProcessType processType;
     if (!decoder.decodeEnum(processType))
         return false;
 
-    request = TextCheckingRequestData(sequence, text, mask, processType);
+    request = TextCheckingRequestData { sequence, text, checkingTypes, processType };
     return true;
 }
 
index fcdfe90..eaa6c20 100644 (file)
@@ -3090,31 +3090,29 @@ void WebViewImpl::handleRequestedCandidates(NSInteger sequenceNumber, NSArray<NS
 #endif
 }
 
-static WebCore::TextCheckingResult textCheckingResultFromNSTextCheckingResult(NSTextCheckingResult *nsResult)
+static constexpr WebCore::TextCheckingType coreTextCheckingType(NSTextCheckingType type)
 {
-    WebCore::TextCheckingResult result;
-
-    // FIXME: Right now we only request candidates for spelling, replacement, and correction, but we plan to
-    // support more types, and we will have to update this at that time.
-    switch ([nsResult resultType]) {
-    case NSTextCheckingTypeSpelling:
-        result.type = WebCore::TextCheckingTypeSpelling;
-        break;
-    case NSTextCheckingTypeReplacement:
-        result.type = WebCore::TextCheckingTypeReplacement;
-        break;
+    switch (type) {
     case NSTextCheckingTypeCorrection:
-        result.type = WebCore::TextCheckingTypeCorrection;
-        break;
+        return WebCore::TextCheckingType::Correction;
+    case NSTextCheckingTypeReplacement:
+        return WebCore::TextCheckingType::Replacement;
+    case NSTextCheckingTypeSpelling:
+        return WebCore::TextCheckingType::Spelling;
     default:
-        result.type = WebCore::TextCheckingTypeNone;
+        return WebCore::TextCheckingType::None;
     }
+}
 
+static WebCore::TextCheckingResult textCheckingResultFromNSTextCheckingResult(NSTextCheckingResult *nsResult)
+{
     NSRange resultRange = [nsResult range];
+
+    WebCore::TextCheckingResult result;
+    result.type = coreTextCheckingType(nsResult.resultType);
     result.location = resultRange.location;
     result.length = resultRange.length;
-    result.replacement = [nsResult replacementString];
-
+    result.replacement = nsResult.replacementString;
     return result;
 }
 
index e7f3dd6..9588b64 100644 (file)
@@ -74,7 +74,7 @@ public:
     static int64_t uniqueSpellDocumentTag(WebPageProxy*);
     static void closeSpellDocumentWithTag(int64_t);
 #if USE(UNIFIED_TEXT_CHECKING)
-    static Vector<WebCore::TextCheckingResult> checkTextOfParagraph(int64_t spellDocumentTag, StringView text, int32_t insertionPoint, uint64_t checkingTypes, bool initialCapitalizationEnabled);
+    static Vector<WebCore::TextCheckingResult> checkTextOfParagraph(int64_t spellDocumentTag, StringView, int32_t insertionPoint, OptionSet<WebCore::TextCheckingType>, bool initialCapitalizationEnabled);
 #endif
     static void checkSpellingOfString(int64_t spellDocumentTag, StringView text, int32_t& misspellingLocation, int32_t& misspellingLength);
     static void checkGrammarOfString(int64_t spellDocumentTag, StringView text, Vector<WebCore::GrammarDetail>&, int32_t& badGrammarLocation, int32_t& badGrammarLength);
index 8acd1b2..01c40be 100644 (file)
@@ -5340,7 +5340,7 @@ int64_t WebPageProxy::spellDocumentTag()
 }
 
 #if USE(UNIFIED_TEXT_CHECKING)
-void WebPageProxy::checkTextOfParagraph(const String& text, uint64_t checkingTypes, int32_t insertionPoint, Vector<TextCheckingResult>& results)
+void WebPageProxy::checkTextOfParagraph(const String& text, OptionSet<TextCheckingType> checkingTypes, int32_t insertionPoint, Vector<TextCheckingResult>& results)
 {
     results = TextChecker::checkTextOfParagraph(spellDocumentTag(), text, insertionPoint, checkingTypes, m_initialCapitalizationEnabled);
 }
index 9f625dd..c90019d 100644 (file)
@@ -1217,7 +1217,7 @@ public:
 #endif
 
 #if USE(UNIFIED_TEXT_CHECKING)
-    void checkTextOfParagraph(const String& text, uint64_t checkingTypes, int32_t insertionPoint, Vector<WebCore::TextCheckingResult>& results);
+    void checkTextOfParagraph(const String& text, OptionSet<WebCore::TextCheckingType> checkingTypes, int32_t insertionPoint, Vector<WebCore::TextCheckingResult>& results);
 #endif
     void getGuessesForWord(const String& word, const String& context, int32_t insertionPoint, Vector<String>& guesses);
 
index 89cafae..b3bd5ec 100644 (file)
@@ -299,7 +299,7 @@ messages -> WebPageProxy {
 
     # Spelling and grammar messages
 #if USE(UNIFIED_TEXT_CHECKING)  
-    CheckTextOfParagraph(String text, uint64_t checkingTypes, int32_t insertionPoint) -> (Vector<WebCore::TextCheckingResult> results)
+    CheckTextOfParagraph(String text, OptionSet<WebCore::TextCheckingType> checkingTypes, int32_t insertionPoint) -> (Vector<WebCore::TextCheckingResult> results)
 #endif
     CheckSpellingOfString(String text) -> (int32_t misspellingLocation, int32_t misspellingLength)
     CheckGrammarOfString(String text) -> (Vector<WebCore::GrammarDetail> results, int32_t badGrammarLocation, int32_t badGrammarLength)
index faff092..b477a3d 100644 (file)
@@ -203,9 +203,9 @@ void TextChecker::requestCheckingOfString(Ref<TextCheckerCompletion>&& completio
 #if ENABLE(SPELLCHECK)
     TextCheckingRequestData request = completion->textCheckingRequestData();
     ASSERT(request.sequence() != unrequestedTextCheckingSequence);
-    ASSERT(request.mask() != TextCheckingTypeNone);
+    ASSERT(request.checkingTypes());
 
-    completion->didFinishCheckingText(checkTextOfParagraph(completion->spellDocumentTag(), request.text(), insertionPoint, request.mask(), false));
+    completion->didFinishCheckingText(checkTextOfParagraph(completion->spellDocumentTag(), request.text(), insertionPoint, request.checkingTypes(), false));
 #else
     UNUSED_PARAM(completion);
 #endif
@@ -240,16 +240,16 @@ static unsigned nextWordOffset(StringView text, unsigned currentOffset)
 #endif
 
 #if USE(UNIFIED_TEXT_CHECKING)
-Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, StringView text, int32_t insertionPoint, uint64_t checkingTypes, bool)
+Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, StringView text, int32_t insertionPoint, OptionSet<TextCheckingType> checkingTypes, bool)
 {
     UNUSED_PARAM(insertionPoint);
 #if ENABLE(SPELLCHECK)
-    if (!(checkingTypes & TextCheckingTypeSpelling))
-        return Vector<TextCheckingResult>();
+    if (!checkingTypes.contains(TextCheckingType::Spelling))
+        return { };
 
     UBreakIterator* textIterator = wordBreakIterator(text);
     if (!textIterator)
-        return Vector<TextCheckingResult>();
+        return { };
 
     // Omit the word separators at the beginning/end of the text to don't unnecessarily
     // involve the client to check spelling for them.
@@ -267,7 +267,7 @@ Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocume
             break;
 
         TextCheckingResult misspellingResult;
-        misspellingResult.type = TextCheckingTypeSpelling;
+        misspellingResult.type = TextCheckingType::Spelling;
         misspellingResult.location = offset + misspellingLocation;
         misspellingResult.length = misspellingLength;
         paragraphCheckingResult.append(misspellingResult);
index 26e352d..068db47 100644 (file)
@@ -145,7 +145,7 @@ void TextChecker::closeSpellDocumentWithTag(int64_t)
 
 #if USE(UNIFIED_TEXT_CHECKING)
 
-Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t, StringView, int32_t, uint64_t, bool)
+Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t, StringView, int32_t, OptionSet<TextCheckingType>, bool)
 {
     notImplemented();
     return Vector<TextCheckingResult>();
index c92fe5f..9a0d517 100644 (file)
@@ -326,7 +326,7 @@ void TextChecker::closeSpellDocumentWithTag(int64_t tag)
 
 #if USE(UNIFIED_TEXT_CHECKING)
 
-Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, StringView text, int32_t insertionPoint, uint64_t checkingTypes, bool initialCapitalizationEnabled)
+Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, StringView text, int32_t insertionPoint, OptionSet<TextCheckingType> checkingTypes, bool initialCapitalizationEnabled)
 {
     Vector<TextCheckingResult> results;
 
@@ -340,7 +340,7 @@ Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocume
 #endif
     NSArray *incomingResults = [[NSSpellChecker sharedSpellChecker] checkString:textString.get()
                                                                           range:NSMakeRange(0, text.length())
-                                                                          types:checkingTypes | NSTextCheckingTypeOrthography
+                                                                          types:nsTextCheckingTypes(checkingTypes) | NSTextCheckingTypeOrthography
                                                                         options:options
                                                          inSpellDocumentWithTag:spellDocumentTag 
                                                                     orthography:NULL
@@ -350,16 +350,16 @@ Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocume
         NSTextCheckingType resultType = [incomingResult resultType];
         ASSERT(resultRange.location != NSNotFound);
         ASSERT(resultRange.length > 0);
-        if (resultType == NSTextCheckingTypeSpelling && (checkingTypes & NSTextCheckingTypeSpelling)) {
+        if (resultType == NSTextCheckingTypeSpelling && checkingTypes.contains(TextCheckingType::Spelling)) {
             TextCheckingResult result;
-            result.type = TextCheckingTypeSpelling;
+            result.type = TextCheckingType::Spelling;
             result.location = resultRange.location;
             result.length = resultRange.length;
             results.append(result);
-        } else if (resultType == NSTextCheckingTypeGrammar && (checkingTypes & NSTextCheckingTypeGrammar)) {
+        } else if (resultType == NSTextCheckingTypeGrammar && checkingTypes.contains(TextCheckingType::Grammar)) {
             TextCheckingResult result;
             NSArray *details = [incomingResult grammarDetails];
-            result.type = TextCheckingTypeGrammar;
+            result.type = TextCheckingType::Grammar;
             result.location = resultRange.location;
             result.length = resultRange.length;
             for (NSDictionary *incomingDetail in details) {
@@ -379,37 +379,37 @@ Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocume
                 result.details.append(detail);
             }
             results.append(result);
-        } else if (resultType == NSTextCheckingTypeLink && (checkingTypes & NSTextCheckingTypeLink)) {
+        } else if (resultType == NSTextCheckingTypeLink && checkingTypes.contains(TextCheckingType::Link)) {
             TextCheckingResult result;
-            result.type = TextCheckingTypeLink;
+            result.type = TextCheckingType::Link;
             result.location = resultRange.location;
             result.length = resultRange.length;
             result.replacement = [[incomingResult URL] absoluteString];
             results.append(result);
-        } else if (resultType == NSTextCheckingTypeQuote && (checkingTypes & NSTextCheckingTypeQuote)) {
+        } else if (resultType == NSTextCheckingTypeQuote && checkingTypes.contains(TextCheckingType::Quote)) {
             TextCheckingResult result;
-            result.type = TextCheckingTypeQuote;
+            result.type = TextCheckingType::Quote;
             result.location = resultRange.location;
             result.length = resultRange.length;
             result.replacement = [incomingResult replacementString];
             results.append(result);
-        } else if (resultType == NSTextCheckingTypeDash && (checkingTypes & NSTextCheckingTypeDash)) {
+        } else if (resultType == NSTextCheckingTypeDash && checkingTypes.contains(TextCheckingType::Dash)) {
             TextCheckingResult result;
-            result.type = TextCheckingTypeDash;
+            result.type = TextCheckingType::Dash;
             result.location = resultRange.location;
             result.length = resultRange.length;
             result.replacement = [incomingResult replacementString];
             results.append(result);
-        } else if (resultType == NSTextCheckingTypeReplacement && (checkingTypes & NSTextCheckingTypeReplacement)) {
+        } else if (resultType == NSTextCheckingTypeReplacement && checkingTypes.contains(TextCheckingType::Replacement)) {
             TextCheckingResult result;
-            result.type = TextCheckingTypeReplacement;
+            result.type = TextCheckingType::Replacement;
             result.location = resultRange.location;
             result.length = resultRange.length;
             result.replacement = [incomingResult replacementString];
             results.append(result);
-        } else if (resultType == NSTextCheckingTypeCorrection && (checkingTypes & NSTextCheckingTypeCorrection)) {
+        } else if (resultType == NSTextCheckingTypeCorrection && checkingTypes.contains(TextCheckingType::Correction)) {
             TextCheckingResult result;
-            result.type = TextCheckingTypeCorrection;
+            result.type = TextCheckingType::Correction;
             result.location = resultRange.location;
             result.length = resultRange.length;
             result.replacement = [incomingResult replacementString];
@@ -420,7 +420,7 @@ Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocume
     return results;
 }
 
-#endif
+#endif // USE(UNIFIED_TEXT_CHECKING)
 
 void TextChecker::checkSpellingOfString(int64_t, StringView, int32_t&, int32_t&)
 {
index 0926d7b..2e76b75 100644 (file)
@@ -129,10 +129,12 @@ void TextChecker::requestCheckingOfString(Ref<TextCheckerCompletion>&&, int32_t)
 }
 
 #if USE(UNIFIED_TEXT_CHECKING)
-Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t, StringView, int32_t, uint64_t, bool)
+
+Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t, StringView, int32_t, OptionSet<TextCheckingType>, bool)
 {
-    return Vector<TextCheckingResult>();
+    return { };
 }
-#endif // USE(UNIFIED_TEXT_CHECKING)
+
+#endif
 
 } // namespace WebKit
index d87a538..fe5b605 100644 (file)
@@ -467,7 +467,7 @@ bool WebEditorClient::shouldEraseMarkersAfterChangeSelection(WebCore::TextChecki
 {
     // This prevents erasing spelling markers on OS X Lion or later to match AppKit on these Mac OS X versions.
 #if PLATFORM(COCOA)
-    return type != TextCheckingTypeSpelling;
+    return type != TextCheckingType::Spelling;
 #else
     UNUSED_PARAM(type);
     return true;
@@ -518,12 +518,10 @@ static int32_t insertionPointFromCurrentSelection(const VisibleSelection& curren
 }
 
 #if USE(UNIFIED_TEXT_CHECKING)
-Vector<TextCheckingResult> WebEditorClient::checkTextOfParagraph(StringView stringView, WebCore::TextCheckingTypeMask checkingTypes, const VisibleSelection& currentSelection)
+Vector<TextCheckingResult> WebEditorClient::checkTextOfParagraph(StringView stringView, OptionSet<WebCore::TextCheckingType> checkingTypes, const VisibleSelection& currentSelection)
 {
     Vector<TextCheckingResult> results;
-
     m_page->sendSync(Messages::WebPageProxy::CheckTextOfParagraph(stringView.toStringWithoutCopying(), checkingTypes, insertionPointFromCurrentSelection(currentSelection)), Messages::WebPageProxy::CheckTextOfParagraph::Reply(results));
-
     return results;
 }
 #endif
index be66faf..75c675a 100644 (file)
@@ -143,7 +143,7 @@ private:
     void checkGrammarOfString(StringView, Vector<WebCore::GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength) final;
 
 #if USE(UNIFIED_TEXT_CHECKING)
-    Vector<WebCore::TextCheckingResult> checkTextOfParagraph(StringView, WebCore::TextCheckingTypeMask checkingTypes, const WebCore::VisibleSelection& currentSelection) final;
+    Vector<WebCore::TextCheckingResult> checkTextOfParagraph(StringView, OptionSet<WebCore::TextCheckingType> checkingTypes, const WebCore::VisibleSelection& currentSelection) final;
 #endif
 
     void updateSpellingUIWithGrammarString(const String&, const WebCore::GrammarDetail&) final;
index b9b5076..df66f6c 100644 (file)
@@ -1,5 +1,29 @@
 2018-08-21  Daniel Bates  <dabates@apple.com>
 
+        Replace TextCheckingTypeMask with OptionSet
+        https://bugs.webkit.org/show_bug.cgi?id=188678
+
+        Reviewed by Antti Koivisto.
+
+        Currently we have code in WebEditorClient::checkTextOfParagraph() that incorrectly assumes
+        that the enumerators of TextCheckingType have a one-to-one correspondence with NSTextCheckingType.
+        (This is not the case because there is not corresponding NSTextCheckingType for TextCheckingTypeShowCorrectionPanel).
+        We now explicitly convert from OptionSet<TextCheckingType> to NSTextCheckingTypes.
+
+        * WebCoreSupport/WebEditorClient.h:
+        * WebCoreSupport/WebEditorClient.mm:
+        (WebEditorClient::checkTextOfParagraph):
+        (WebEditorClient::shouldEraseMarkersAfterChangeSelection const):
+        (core): Fix up code style nits; compare resultType on the right-hand side instead of the
+        left as this is more readable and unncessary now that modern compilers like Clang have
+        diagnostics to catch accidental assignments when equality was intended.
+        (WebEditorClient::didCheckSucceed):
+        * WebView/WebView.mm:
+        (coreTextCheckingType):
+        (textCheckingResultFromNSTextCheckingResult):
+
+2018-08-21  Daniel Bates  <dabates@apple.com>
+
         [iOS][WK1] Support toggling continuous spell checking from tests
         https://bugs.webkit.org/show_bug.cgi?id=188763
 
index da35efe..bb35235 100644 (file)
@@ -154,7 +154,7 @@ private:
     void checkSpellingOfString(StringView, int* misspellingLocation, int* misspellingLength) final;
     String getAutoCorrectSuggestionForMisspelledWord(const String&) final;
     void checkGrammarOfString(StringView, Vector<WebCore::GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength) final;
-    Vector<WebCore::TextCheckingResult> checkTextOfParagraph(StringView, WebCore::TextCheckingTypeMask checkingTypes, const WebCore::VisibleSelection& currentSelection) final;
+    Vector<WebCore::TextCheckingResult> checkTextOfParagraph(StringView, OptionSet<WebCore::TextCheckingType> checkingTypes, const WebCore::VisibleSelection& currentSelection) final;
     void updateSpellingUIWithGrammarString(const String&, const WebCore::GrammarDetail&) final;
     void updateSpellingUIWithMisspelledWord(const String&) final;
     void showSpellingUI(bool show) final;
index 7ae5685..e28112d 100644 (file)
@@ -933,9 +933,9 @@ bool WebEditorClient::performTwoStepDrop(DocumentFragment& fragment, Range& dest
     return false;
 }
 
-Vector<TextCheckingResult> WebEditorClient::checkTextOfParagraph(StringView string, TextCheckingTypeMask checkingTypes, const VisibleSelection&)
+Vector<TextCheckingResult> WebEditorClient::checkTextOfParagraph(StringView string, OptionSet<TextCheckingType> checkingTypes, const VisibleSelection&)
 {
-    ASSERT(checkingTypes & NSTextCheckingTypeSpelling);
+    ASSERT(checkingTypes.contains(TextCheckingType::Spelling));
 
     Vector<TextCheckingResult> results;
 
@@ -944,7 +944,7 @@ Vector<TextCheckingResult> WebEditorClient::checkTextOfParagraph(StringView stri
         NSRange resultRange = [incomingResult rangeValue];
         ASSERT(resultRange.location != NSNotFound && resultRange.length > 0);
         TextCheckingResult result;
-        result.type = TextCheckingTypeSpelling;
+        result.type = TextCheckingType::Spelling;
         result.location = resultRange.location;
         result.length = resultRange.length;
         results.append(result);
@@ -965,7 +965,7 @@ bool WebEditorClient::performTwoStepDrop(DocumentFragment&, Range&, bool)
 bool WebEditorClient::shouldEraseMarkersAfterChangeSelection(TextCheckingType type) const
 {
     // This prevents erasing spelling markers on OS X Lion or later to match AppKit on these Mac OS X versions.
-    return type != TextCheckingTypeSpelling;
+    return type != TextCheckingType::Spelling;
 }
 
 void WebEditorClient::ignoreWordInSpellDocument(const String& text)
@@ -1028,7 +1028,7 @@ void WebEditorClient::checkGrammarOfString(StringView text, Vector<GrammarDetail
     }
 }
 
-static Vector<TextCheckingResult> core(NSArray *incomingResults, TextCheckingTypeMask checkingTypes)
+static Vector<TextCheckingResult> core(NSArray *incomingResults, OptionSet<TextCheckingType> checkingTypes)
 {
     Vector<TextCheckingResult> results;
 
@@ -1037,16 +1037,16 @@ static Vector<TextCheckingResult> core(NSArray *incomingResults, TextCheckingTyp
         NSTextCheckingType resultType = [incomingResult resultType];
         ASSERT(resultRange.location != NSNotFound);
         ASSERT(resultRange.length > 0);
-        if (NSTextCheckingTypeSpelling == resultType && 0 != (checkingTypes & NSTextCheckingTypeSpelling)) {
+        if (resultType == NSTextCheckingTypeSpelling && checkingTypes.contains(TextCheckingType::Spelling)) {
             TextCheckingResult result;
-            result.type = TextCheckingTypeSpelling;
+            result.type = TextCheckingType::Spelling;
             result.location = resultRange.location;
             result.length = resultRange.length;
             results.append(result);
-        } else if (NSTextCheckingTypeGrammar == resultType && 0 != (checkingTypes & NSTextCheckingTypeGrammar)) {
+        } else if (resultType == NSTextCheckingTypeGrammar && checkingTypes.contains(TextCheckingType::Grammar)) {
             TextCheckingResult result;
             NSArray *details = [incomingResult grammarDetails];
-            result.type = TextCheckingTypeGrammar;
+            result.type = TextCheckingType::Grammar;
             result.location = resultRange.location;
             result.length = resultRange.length;
             for (NSDictionary *incomingDetail in details) {
@@ -1066,37 +1066,37 @@ static Vector<TextCheckingResult> core(NSArray *incomingResults, TextCheckingTyp
                 result.details.append(detail);
             }
             results.append(result);
-        } else if (NSTextCheckingTypeLink == resultType && 0 != (checkingTypes & NSTextCheckingTypeLink)) {
+        } else if (resultType == NSTextCheckingTypeLink && checkingTypes.contains(TextCheckingType::Link)) {
             TextCheckingResult result;
-            result.type = TextCheckingTypeLink;
+            result.type = TextCheckingType::Link;
             result.location = resultRange.location;
             result.length = resultRange.length;
             result.replacement = [[incomingResult URL] absoluteString];
             results.append(result);
-        } else if (NSTextCheckingTypeQuote == resultType && 0 != (checkingTypes & NSTextCheckingTypeQuote)) {
+        } else if (resultType == NSTextCheckingTypeQuote && checkingTypes.contains(TextCheckingType::Quote)) {
             TextCheckingResult result;
-            result.type = TextCheckingTypeQuote;
+            result.type = TextCheckingType::Quote;
             result.location = resultRange.location;
             result.length = resultRange.length;
             result.replacement = [incomingResult replacementString];
             results.append(result);
-        } else if (NSTextCheckingTypeDash == resultType && 0 != (checkingTypes & NSTextCheckingTypeDash)) {
+        } else if (resultType == NSTextCheckingTypeDash && checkingTypes.contains(TextCheckingType::Dash)) {
             TextCheckingResult result;
-            result.type = TextCheckingTypeDash;
+            result.type = TextCheckingType::Dash;
             result.location = resultRange.location;
             result.length = resultRange.length;
             result.replacement = [incomingResult replacementString];
             results.append(result);
-        } else if (NSTextCheckingTypeReplacement == resultType && 0 != (checkingTypes & NSTextCheckingTypeReplacement)) {
+        } else if (resultType == NSTextCheckingTypeReplacement && checkingTypes.contains(TextCheckingType::Replacement)) {
             TextCheckingResult result;
-            result.type = TextCheckingTypeReplacement;
+            result.type = TextCheckingType::Replacement;
             result.location = resultRange.location;
             result.length = resultRange.length;
             result.replacement = [incomingResult replacementString];
             results.append(result);
-        } else if (NSTextCheckingTypeCorrection == resultType && 0 != (checkingTypes & NSTextCheckingTypeCorrection)) {
+        } else if (resultType == NSTextCheckingTypeCorrection && checkingTypes.contains(TextCheckingType::Correction)) {
             TextCheckingResult result;
-            result.type = TextCheckingTypeCorrection;
+            result.type = TextCheckingType::Correction;
             result.location = resultRange.location;
             result.length = resultRange.length;
             result.replacement = [incomingResult replacementString];
@@ -1116,13 +1116,13 @@ static int insertionPointFromCurrentSelection(const VisibleSelection& currentSel
 }
 #endif
 
-Vector<TextCheckingResult> WebEditorClient::checkTextOfParagraph(StringView string, TextCheckingTypeMask checkingTypes, const VisibleSelection& currentSelection)
+Vector<TextCheckingResult> WebEditorClient::checkTextOfParagraph(StringView string, OptionSet<TextCheckingType> coreCheckingTypes, const VisibleSelection& currentSelection)
 {
     NSDictionary *options = nil;
 #if HAVE(ADVANCED_SPELL_CHECKING)
     options = @{ NSTextCheckingInsertionPointKey :  [NSNumber numberWithUnsignedInteger:insertionPointFromCurrentSelection(currentSelection)] };
 #endif
-    return core([[NSSpellChecker sharedSpellChecker] checkString:string.createNSStringWithoutCopying().get() range:NSMakeRange(0, string.length()) types:(checkingTypes | NSTextCheckingTypeOrthography) options:options inSpellDocumentWithTag:spellCheckerDocumentTag() orthography:NULL wordCount:NULL], checkingTypes);
+    return core([[NSSpellChecker sharedSpellChecker] checkString:string.createNSStringWithoutCopying().get() range:NSMakeRange(0, string.length()) types:(nsTextCheckingTypes(coreCheckingTypes) | NSTextCheckingTypeOrthography) options:options inSpellDocumentWithTag:spellCheckerDocumentTag() orthography:NULL wordCount:NULL], coreCheckingTypes);
 }
 
 void WebEditorClient::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail)
@@ -1327,7 +1327,7 @@ void WebEditorClient::handleAcceptedCandidateWithSoftSpaces(TextCheckingResult a
 void WebEditorClient::didCheckSucceed(int sequence, NSArray* results)
 {
     ASSERT_UNUSED(sequence, sequence == m_textCheckingRequest->data().sequence());
-    m_textCheckingRequest->didSucceed(core(results, m_textCheckingRequest->data().mask()));
+    m_textCheckingRequest->didSucceed(core(results, m_textCheckingRequest->data().checkingTypes()));
     m_textCheckingRequest = nullptr;
 }
 
index 11cb3ba..b892734 100644 (file)
@@ -7283,29 +7283,29 @@ static WebFrame *incrementFrame(WebFrame *frame, WebFindOptions options = 0)
     return nil;
 }
 
-static TextCheckingResult textCheckingResultFromNSTextCheckingResult(NSTextCheckingResult *nsResult)
+constexpr TextCheckingType coreTextCheckingType(NSTextCheckingType type)
 {
-    WebCore::TextCheckingResult result;
-
-    switch ([nsResult resultType]) {
-    case NSTextCheckingTypeSpelling:
-        result.type = WebCore::TextCheckingTypeSpelling;
-        break;
-    case NSTextCheckingTypeReplacement:
-        result.type = WebCore::TextCheckingTypeReplacement;
-        break;
+    switch (type) {
     case NSTextCheckingTypeCorrection:
-        result.type = WebCore::TextCheckingTypeCorrection;
-        break;
+        return TextCheckingType::Correction;
+    case NSTextCheckingTypeReplacement:
+        return TextCheckingType::Replacement;
+    case NSTextCheckingTypeSpelling:
+        return TextCheckingType::Spelling;
     default:
-        result.type = WebCore::TextCheckingTypeNone;
+        return TextCheckingType::None;
     }
+}
 
+static TextCheckingResult textCheckingResultFromNSTextCheckingResult(NSTextCheckingResult *nsResult)
+{
     NSRange resultRange = nsResult.range;
+
+    TextCheckingResult result;
+    result.type = coreTextCheckingType(nsResult.resultType);
     result.location = resultRange.location;
     result.length = resultRange.length;
     result.replacement = nsResult.replacementString;
-
     return result;
 }