|
|
DescriptionAdd SpellCheckMarkerList in preparation for DocumentMarkerController refactor
Split off from https://codereview.chromium.org/2723663002
This CL depends on the CL that adds CompositionMarkerList:
https://codereview.chromium.org/2773883003
One important thing that makes SpellCheckMarkerList special is that it merges
markers with touching endpoints. I've added some test cases for this behavior
in SpellCheckMarkerListTest.cpp.
BUG=707867
Patch Set 1 #Patch Set 2 : Add DCHECK that markers being inserted are of correct type #
Total comments: 11
Patch Set 3 : Make requested changes #Patch Set 4 : Restore RemoveMarkersForWords test case #Patch Set 5 : push_back() => add() in test #Patch Set 6 : Rebase (Vector::remove() => Vector::erase()) #Patch Set 7 : Optimize case where markers are being added in order #
Total comments: 1
Patch Set 8 : Remove unused stuff from test #Patch Set 9 : Rebase #
Total comments: 5
Patch Set 10 : Fix nits, use std::copy_if() #Patch Set 11 : Rebase #Patch Set 12 : Rebase #
Depends on Patchset: Dependent Patchsets: Messages
Total messages: 60 (45 generated)
rlanday@chromium.org changed reviewers: + xiaochengh@chromium.org, yosin@chromium.org
rlanday@chromium.org changed required reviewers: + yosin@chromium.org
The CQ bit was checked by rlanday@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... File third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp (right): https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:15: static bool doesNotOverlap(const Member<DocumentMarker>& lhv, The name doesn't match what it does. Btw, I just realized that the "endsBefore" in DML.cpp also has a wrong name... Maybe a better idea is to use lambda expressions? https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:28: void SpellCheckMarkerList::push_back(DocumentMarker* marker) { Hmm... We need to be more careful about the function names, because it's not doing a push_back. To avoid confusing names while keeping the interface compact, how about just renaming the function as "add"? Besides, please add a comment that this function merges the new marker with existing overlapping ones. https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:44: m_markers.remove(it - m_markers.begin()); This leads to quadratic running time. Could you reduce it to linear? https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:48: void SpellCheckMarkerList::removeMarkersForWords(const Text& textNode, Let's take a String parameter to remove the dependency on DOM objects. https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... File third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListTest.cpp (right): https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListTest.cpp:84: TEST_F(SpellCheckMarkerListTest, PushBackMerging) { Could you split the test case into four independent ones? Ideally, we would like to avoid dependency between test cases.
https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... File third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp (right): https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:44: m_markers.remove(it - m_markers.begin()); On 2017/03/25 at 18:55:52, Xiaocheng wrote: > This leads to quadratic running time. Could you reduce it to linear? Ah, I did notice this can be improved, I must've been in a hurry to upload this CL :)
https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... File third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.h (right): https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.h:14: class CORE_EXPORT SpellCheckMarkerList : public EditingMarkerList { nit: Please mark this class |final| https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.h:19: DocumentMarker::MarkerType allowedMarkerType() const final; nit: interface implementations should be in |private| section. https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.h:27: DocumentMarker::MarkerType m_type; nit: s/DocumentMarker::MarkerType/const DocumentMarker::MarkerType/
https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... File third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.h (right): https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.h:19: DocumentMarker::MarkerType allowedMarkerType() const final; On 2017/03/27 at 05:02:51, yosin_UTC9 wrote: > nit: interface implementations should be in |private| section. Sorry, I don't understand what you mean here; these methods are all public in DocumentMarkerList and won't be callable on SpellCheckMarkerList if I make them private here. E.g. SpellCheckMarkerList will get a compilation error trying to call add().
https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... File third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.h (right): https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.h:19: DocumentMarker::MarkerType allowedMarkerType() const final; On 2017/03/27 at 21:59:24, rlanday wrote: > On 2017/03/27 at 05:02:51, yosin_UTC9 wrote: > > nit: interface implementations should be in |private| section. > > Sorry, I don't understand what you mean here; these methods are all public in DocumentMarkerList and won't be callable on SpellCheckMarkerList if I make them private here. E.g. SpellCheckMarkerList will get a compilation error trying to call add(). In most cases, subclasses put overridden functions in their private sections, even though the superclass declares the function as public. Just like what you did for SetCharacterDataCommand, where SCDC::doApply and SCDC::doUnapply are private, though they override public EditCommand::doApply and EditCommand::doUnapply.
The CQ bit was checked by rlanday@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
On 2017/03/27 at 22:08:24, xiaochengh wrote: > https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... > File third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.h (right): > > https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... > third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.h:19: DocumentMarker::MarkerType allowedMarkerType() const final; > On 2017/03/27 at 21:59:24, rlanday wrote: > > On 2017/03/27 at 05:02:51, yosin_UTC9 wrote: > > > nit: interface implementations should be in |private| section. > > > > Sorry, I don't understand what you mean here; these methods are all public in DocumentMarkerList and won't be callable on SpellCheckMarkerList if I make them private here. E.g. SpellCheckMarkerList will get a compilation error trying to call add(). > > In most cases, subclasses put overridden functions in their private sections, even though the superclass declares the function as public. > > Just like what you did for SetCharacterDataCommand, where SCDC::doApply and SCDC::doUnapply are private, though they override public EditCommand::doApply and EditCommand::doUnapply. Sorry, I still don't understand. That doesn't seem like good design to me. As I mentioned, SpellCheckMarkerListTest will not compile if I do this. I tried to find a reference for this rule and I found this instead: https://isocpp.org/wiki/faq/proper-inheritance#hiding-inherited-public "Should I hide member functions that were public in my base class? Never, never, never do this. Never. Never!"
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: android_arm64_dbg_recipe on master.tryserver.chromium.android (JOB_FAILED, https://build.chromium.org/p/tryserver.chromium.android/builders/android_arm6...)
On 2017/03/27 at 22:22:01, rlanday wrote: > On 2017/03/27 at 22:08:24, xiaochengh wrote: > > https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... > > File third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.h (right): > > > > https://codereview.chromium.org/2770413003/diff/20001/third_party/WebKit/Sour... > > third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.h:19: DocumentMarker::MarkerType allowedMarkerType() const final; > > On 2017/03/27 at 21:59:24, rlanday wrote: > > > On 2017/03/27 at 05:02:51, yosin_UTC9 wrote: > > > > nit: interface implementations should be in |private| section. > > > > > > Sorry, I don't understand what you mean here; these methods are all public in DocumentMarkerList and won't be callable on SpellCheckMarkerList if I make them private here. E.g. SpellCheckMarkerList will get a compilation error trying to call add(). > > > > In most cases, subclasses put overridden functions in their private sections, even though the superclass declares the function as public. > > > > Just like what you did for SetCharacterDataCommand, where SCDC::doApply and SCDC::doUnapply are private, though they override public EditCommand::doApply and EditCommand::doUnapply. > > Sorry, I still don't understand. That doesn't seem like good design to me. As I mentioned, SpellCheckMarkerListTest will not compile if I do this. I tried to find a reference for this rule and I found this instead: > https://isocpp.org/wiki/faq/proper-inheritance#hiding-inherited-public > > "Should I hide member functions that were public in my base class? > Never, never, never do this. Never. Never!" Interesting. There is at least one benefit of hiding member functions: clients are forced to hold a reference to the base class, which reduces the exposure of the subclass. It's helpful when the subclass is considered as an implementation detail that shouldn't be exposed. I actually see both patterns (hide / not hide) in Blink. Maybe we should initiate a discussion thread at chromium-dev@? Btw, to make SpellCheckMarkerListTest compile, just make it hold a Persist<DML>.
On 2017/03/27 at 23:07:44, xiaochengh wrote: > Btw, to make SpellCheckMarkerListTest compile, just make it hold a Persist<DML>. There's supposed to be a test for removeMarkersForWords() too though (it looks like I accidentally deleted it), we can't call that method (at least not without casting) if we use Persist<DML>...
The CQ bit was checked by rlanday@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: linux_chromium_compile_dbg_ng on master.tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/linux_chromium_...)
The CQ bit was checked by rlanday@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
The CQ bit was checked by rlanday@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: ios-simulator on master.tryserver.chromium.mac (JOB_TIMED_OUT, build hasn't started yet, builder probably lacks capacity)
I've added an optimization to SpellCheckMarkerList so add() can be done in (amortized) O(1) time for a marker being added to the end of the list vs. (amortized) O(log n) time (for doing std::lower_bound())
The CQ bit was checked by rlanday@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
lgtm with a nit. https://codereview.chromium.org/2770413003/diff/120001/third_party/WebKit/Sou... File third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListTest.cpp (right): https://codereview.chromium.org/2770413003/diff/120001/third_party/WebKit/Sou... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListTest.cpp:30: std::unique_ptr<DummyPageHolder> m_dummyPageHolder; nit: No need to set up page and document.
The CQ bit was checked by rlanday@chromium.org to run a CQ dry run
On 2017/03/29 at 20:24:21, xiaochengh wrote: > lgtm with a nit. > > https://codereview.chromium.org/2770413003/diff/120001/third_party/WebKit/Sou... > File third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListTest.cpp (right): > > https://codereview.chromium.org/2770413003/diff/120001/third_party/WebKit/Sou... > third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListTest.cpp:30: std::unique_ptr<DummyPageHolder> m_dummyPageHolder; > nit: No need to set up page and document. Updated
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
Still lgtm.
The CQ bit was checked by rlanday@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
https://codereview.chromium.org/2770413003/diff/150001/third_party/WebKit/Sou... File third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp (right): https://codereview.chromium.org/2770413003/diff/150001/third_party/WebKit/Sou... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:23: DCHECK(marker->type() == allowedMarkerType()); nit: Let's use DCHECK_EQ(). If we need to introduce printer, let's introduce printer too for ease of debugging. https://codereview.chromium.org/2770413003/diff/150001/third_party/WebKit/Sou... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:32: auto firstOverlappingIt = std::lower_bound( nit: s/auto/const auto&/ https://codereview.chromium.org/2770413003/diff/150001/third_party/WebKit/Sou... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:40: auto insertedIt = m_markers.begin() + index; nit: s/auto/const auto&/ https://codereview.chromium.org/2770413003/diff/150001/third_party/WebKit/Sou... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:62: for (Member<DocumentMarker> marker : m_markers) { Can we use std::copy_if()[1]? [1] http://en.cppreference.com/w/cpp/algorithm/copy https://codereview.chromium.org/2770413003/diff/150001/third_party/WebKit/Sou... third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:65: String markerText = nodeText.substring(start, length); nit: s/String/const String&/
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: ios-simulator on master.tryserver.chromium.mac (JOB_TIMED_OUT, build hasn't started yet, builder probably lacks capacity)
The CQ bit was checked by rlanday@chromium.org to run a CQ dry run
On 2017/03/30 at 01:33:06, yosin wrote: > https://codereview.chromium.org/2770413003/diff/150001/third_party/WebKit/Sou... > File third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp (right): > > https://codereview.chromium.org/2770413003/diff/150001/third_party/WebKit/Sou... > third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:23: DCHECK(marker->type() == allowedMarkerType()); > nit: Let's use DCHECK_EQ(). If we need to introduce printer, let's introduce printer too for ease of debugging. > > https://codereview.chromium.org/2770413003/diff/150001/third_party/WebKit/Sou... > third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:32: auto firstOverlappingIt = std::lower_bound( > nit: s/auto/const auto&/ > > https://codereview.chromium.org/2770413003/diff/150001/third_party/WebKit/Sou... > third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:40: auto insertedIt = m_markers.begin() + index; > nit: s/auto/const auto&/ > > https://codereview.chromium.org/2770413003/diff/150001/third_party/WebKit/Sou... > third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:62: for (Member<DocumentMarker> marker : m_markers) { > Can we use std::copy_if()[1]? > > [1] http://en.cppreference.com/w/cpp/algorithm/copy > > https://codereview.chromium.org/2770413003/diff/150001/third_party/WebKit/Sou... > third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerList.cpp:65: String markerText = nodeText.substring(start, length); > nit: s/String/const String&/ Updated
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
The CQ bit was checked by rlanday@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
The CQ bit was checked by rlanday@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
Description was changed from ========== Add SpellCheckMarkerList in preparation for DocumentMarkerController refactor Split off from https://codereview.chromium.org/2723663002 This CL depends on the CL that adds CompositionMarkerList: https://codereview.chromium.org/2773883003 One important thing that makes SpellCheckMarkerList special is that it merges markers with touching endpoints. I've added some test cases for this behavior in SpellCheckMarkerListTest.cpp. ========== to ========== Add SpellCheckMarkerList in preparation for DocumentMarkerController refactor Split off from https://codereview.chromium.org/2723663002 This CL depends on the CL that adds CompositionMarkerList: https://codereview.chromium.org/2773883003 One important thing that makes SpellCheckMarkerList special is that it merges markers with touching endpoints. I've added some test cases for this behavior in SpellCheckMarkerListTest.cpp. BUG=707867 ========== |