From 6fa4db9adca96065c1fbe0f6df3c3cbe895e4730 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Mon, 25 Nov 2024 16:24:23 +0100 Subject: [PATCH 1/6] Improve splitRangesOnEmojis complexity --- .../expensify/livemarkdown/MarkdownUtils.java | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java index 8a1537c2a..09c440bea 100644 --- a/android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java @@ -71,7 +71,9 @@ public void setMarkdownStyle(@NonNull MarkdownStyle markdownStyle) { private void splitRangesOnEmojis(List markdownRanges, String type) { List emojiRanges = new ArrayList<>(); - for (MarkdownRange range : markdownRanges) { + List oldRanges = new ArrayList<>(markdownRanges); + markdownRanges.clear(); + for (MarkdownRange range : oldRanges) { if (range.type.equals("emoji")) { emojiRanges.add(range); } @@ -79,24 +81,29 @@ private void splitRangesOnEmojis(List markdownRanges, String type int i = 0; int j = 0; - while (i < markdownRanges.size() && j < emojiRanges.size()) { - MarkdownRange currentRange = markdownRanges.get(i); - MarkdownRange emojiRange = emojiRanges.get(j); - - if (!currentRange.type.equals(type) || currentRange.end < emojiRange.start) { + while (i < oldRanges.size()) { + MarkdownRange currentRange = oldRanges.get(i); + if (!currentRange.type.equals(type)) { + markdownRanges.add(currentRange); i += 1; continue; - } else if (emojiRange.start >= currentRange.start && emojiRange.end <= currentRange.end) { - // Split range - MarkdownRange startRange = new MarkdownRange(currentRange.type, currentRange.start, emojiRange.start - currentRange.start, currentRange.depth); - MarkdownRange endRange = new MarkdownRange(currentRange.type, emojiRange.end, currentRange.end - emojiRange.end, currentRange.depth); - - markdownRanges.add(i + 1, startRange); - markdownRanges.add(i + 2, endRange); - markdownRanges.remove(i); - i = i + 1; } - j += 1; + + // Split range + while(j < emojiRanges.size()){ + MarkdownRange emojiRange = emojiRanges.get(j); + if(emojiRange.start > currentRange.end) break; + + if (emojiRange.start >= currentRange.start && emojiRange.end <= currentRange.end) { + MarkdownRange newRange = new MarkdownRange(currentRange.type, currentRange.start, emojiRange.start - currentRange.start, currentRange.depth); + currentRange = new MarkdownRange(currentRange.type, emojiRange.end, currentRange.end - emojiRange.end, currentRange.depth); + + markdownRanges.add(newRange); + } + j += 1; + } + markdownRanges.add(currentRange); + i += 1; } } From 3e8330756c2ba831b28f1fcb35a62e67d6b2aa5d Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Wed, 27 Nov 2024 12:17:26 +0100 Subject: [PATCH 2/6] move splitRangesOnEmojis to separate file --- .../expensify/livemarkdown/MarkdownUtils.java | 41 +---------------- .../expensify/livemarkdown/RangeSplitter.java | 44 +++++++++++++++++++ 2 files changed, 46 insertions(+), 39 deletions(-) create mode 100644 android/src/main/java/com/expensify/livemarkdown/RangeSplitter.java diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java index 09c440bea..c47d2b705 100644 --- a/android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java @@ -1,5 +1,7 @@ package com.expensify.livemarkdown; +import static com.expensify.livemarkdown.RangeSplitter.splitRangesOnEmojis; + import android.content.res.AssetManager; import android.text.SpannableStringBuilder; import android.text.Spanned; @@ -69,45 +71,6 @@ public void setMarkdownStyle(@NonNull MarkdownStyle markdownStyle) { mMarkdownStyle = markdownStyle; } - private void splitRangesOnEmojis(List markdownRanges, String type) { - List emojiRanges = new ArrayList<>(); - List oldRanges = new ArrayList<>(markdownRanges); - markdownRanges.clear(); - for (MarkdownRange range : oldRanges) { - if (range.type.equals("emoji")) { - emojiRanges.add(range); - } - } - - int i = 0; - int j = 0; - while (i < oldRanges.size()) { - MarkdownRange currentRange = oldRanges.get(i); - if (!currentRange.type.equals(type)) { - markdownRanges.add(currentRange); - i += 1; - continue; - } - - // Split range - while(j < emojiRanges.size()){ - MarkdownRange emojiRange = emojiRanges.get(j); - if(emojiRange.start > currentRange.end) break; - - if (emojiRange.start >= currentRange.start && emojiRange.end <= currentRange.end) { - MarkdownRange newRange = new MarkdownRange(currentRange.type, currentRange.start, emojiRange.start - currentRange.start, currentRange.depth); - currentRange = new MarkdownRange(currentRange.type, emojiRange.end, currentRange.end - emojiRange.end, currentRange.depth); - - markdownRanges.add(newRange); - } - j += 1; - } - markdownRanges.add(currentRange); - i += 1; - } - } - - private List parseRanges(String rangesJSON, String innerText) { List markdownRanges = new ArrayList<>(); try { diff --git a/android/src/main/java/com/expensify/livemarkdown/RangeSplitter.java b/android/src/main/java/com/expensify/livemarkdown/RangeSplitter.java new file mode 100644 index 000000000..78bde86c7 --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/RangeSplitter.java @@ -0,0 +1,44 @@ +package com.expensify.livemarkdown; + +import java.util.ArrayList; +import java.util.List; + +public class RangeSplitter { + public static void splitRangesOnEmojis(List markdownRanges, String type) { + List emojiRanges = new ArrayList<>(); + List oldRanges = new ArrayList<>(markdownRanges); + markdownRanges.clear(); + for (MarkdownRange range : oldRanges) { + if (range.type.equals("emoji")) { + emojiRanges.add(range); + } + } + + int i = 0; + int j = 0; + while (i < oldRanges.size()) { + MarkdownRange currentRange = oldRanges.get(i); + if (!currentRange.type.equals(type)) { + markdownRanges.add(currentRange); + i += 1; + continue; + } + + // Split range + while(j < emojiRanges.size()){ + MarkdownRange emojiRange = emojiRanges.get(j); + if(emojiRange.start > currentRange.end) break; + + if (emojiRange.start >= currentRange.start && emojiRange.end <= currentRange.end) { + MarkdownRange newRange = new MarkdownRange(currentRange.type, currentRange.start, emojiRange.start - currentRange.start, currentRange.depth); + currentRange = new MarkdownRange(currentRange.type, emojiRange.end, currentRange.end - emojiRange.end, currentRange.depth); + + markdownRanges.add(newRange); + } + j += 1; + } + markdownRanges.add(currentRange); + i += 1; + } + } +} From 8fe38f335a35415674f55c6b86bd05c73b403f3a Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Wed, 27 Nov 2024 12:18:43 +0100 Subject: [PATCH 3/6] add tests --- android/build.gradle | 2 + .../livemarkdown/RangeSplitterTest.java | 89 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java diff --git a/android/build.gradle b/android/build.gradle index 6aa3061f5..56f31a536 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -171,6 +171,8 @@ repositories { dependencies { implementation "com.facebook.react:react-android" // version substituted by RNGP implementation "com.facebook.react:hermes-android" // version substituted by RNGP + + testImplementation 'junit:junit:4.13.2' } if (isNewArchitectureEnabled()) { diff --git a/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java b/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java new file mode 100644 index 000000000..791cbd1a5 --- /dev/null +++ b/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java @@ -0,0 +1,89 @@ +package com.expensify.livemarkdown; + +import static com.expensify.livemarkdown.RangeSplitter.splitRangesOnEmojis; + + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class RangeSplitterTest { + + private void testRange(MarkdownRange range, int start, int end, String type){ + assertEquals(start, range.start); + assertEquals(end, range.end); + assertEquals(type, range.type); + } + + @Test + public void testNoOverlap() { + List markdownRanges = new ArrayList<>(); + markdownRanges.add(new MarkdownRange("strikethrough", 0, 10, 1)); + markdownRanges.add(new MarkdownRange("emoji", 12, 2,1)); + + splitRangesOnEmojis(markdownRanges, "strikethrough"); + + assertEquals(2, markdownRanges.size()); + + testRange(markdownRanges.get(0), 0, 10, "strikethrough"); + testRange(markdownRanges.get(1), 12, 14, "emoji"); + } + + @Test + public void testOverlapWrongType() { + List markdownRanges = new ArrayList<>(); + markdownRanges.add(new MarkdownRange("strikethrough", 0, 10, 1)); + markdownRanges.add(new MarkdownRange("emoji", 3, 4, 1)); + + splitRangesOnEmojis(markdownRanges, "italic"); + + assertEquals(2, markdownRanges.size()); + testRange(markdownRanges.get(0), 0, 10, "strikethrough"); + testRange(markdownRanges.get(1), 3, 7, "emoji"); + } + + @Test + public void testSingleOverlap(){ + List markdownRanges = new ArrayList<>(); + markdownRanges.add(new MarkdownRange("strikethrough", 0, 10, 1)); + markdownRanges.add(new MarkdownRange("emoji", 3, 4, 1)); // This should split the strikethrough range + + splitRangesOnEmojis(markdownRanges, "strikethrough"); + + // Sort is needed because ranges may get mixed while splitting + Collections.sort(markdownRanges, (r1, r2) -> Integer.compare(r1.start, r2.start)); + + assertEquals(3, markdownRanges.size()); + testRange(markdownRanges.get(0), 0 ,3, "strikethrough"); + testRange(markdownRanges.get(1), 3 ,7, "emoji"); + testRange(markdownRanges.get(2), 7 ,10, "strikethrough"); + } + + @Test + public void testMultipleOverlapsMultipleTypes(){ + List markdownRanges = new ArrayList<>(); + markdownRanges.add(new MarkdownRange("italic", 0, 20, 1)); + markdownRanges.add(new MarkdownRange("strikethrough", 2, 12, 1)); + markdownRanges.add(new MarkdownRange("emoji", 3, 1, 1)); + markdownRanges.add(new MarkdownRange("emoji", 8, 2, 1)); + markdownRanges.add(new MarkdownRange("strikethrough", 22, 5, 1)); + + splitRangesOnEmojis(markdownRanges, "strikethrough"); + + // Sort is needed because ranges may get mixed while splitting + Collections.sort(markdownRanges, (r1, r2) -> Integer.compare(r1.start, r2.start)); + + assertEquals(7, markdownRanges.size()); + testRange(markdownRanges.get(0), 0 ,20, "italic"); + testRange(markdownRanges.get(1), 2 ,3, "strikethrough"); + testRange(markdownRanges.get(2), 3 ,4, "emoji"); + testRange(markdownRanges.get(3), 4 , 8, "strikethrough"); + testRange(markdownRanges.get(4), 8 ,10, "emoji"); + testRange(markdownRanges.get(5), 10 ,14, "strikethrough"); + testRange(markdownRanges.get(6), 22 ,27, "strikethrough"); + } +} From 0d8327e9a492239e50cc67c9495ccfafae971568 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Wed, 11 Dec 2024 10:27:51 +0100 Subject: [PATCH 4/6] fix tests --- .../com/expensify/livemarkdown/RangeSplitterTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java b/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java index 791cbd1a5..b4bf69e2b 100644 --- a/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java +++ b/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java @@ -14,9 +14,9 @@ public class RangeSplitterTest { private void testRange(MarkdownRange range, int start, int end, String type){ - assertEquals(start, range.start); - assertEquals(end, range.end); - assertEquals(type, range.type); + assertEquals(start, range.getStart()); + assertEquals(end, range.getEnd()); + assertEquals(type, range.getType()); } @Test @@ -55,7 +55,7 @@ public void testSingleOverlap(){ splitRangesOnEmojis(markdownRanges, "strikethrough"); // Sort is needed because ranges may get mixed while splitting - Collections.sort(markdownRanges, (r1, r2) -> Integer.compare(r1.start, r2.start)); + Collections.sort(markdownRanges, (r1, r2) -> Integer.compare(r1.getStart(), r2.getStart())); assertEquals(3, markdownRanges.size()); testRange(markdownRanges.get(0), 0 ,3, "strikethrough"); @@ -75,7 +75,7 @@ public void testMultipleOverlapsMultipleTypes(){ splitRangesOnEmojis(markdownRanges, "strikethrough"); // Sort is needed because ranges may get mixed while splitting - Collections.sort(markdownRanges, (r1, r2) -> Integer.compare(r1.start, r2.start)); + Collections.sort(markdownRanges, (r1, r2) -> Integer.compare(r1.getStart(), r2.getStart())); assertEquals(7, markdownRanges.size()); testRange(markdownRanges.get(0), 0 ,20, "italic"); From cea5128337026016393690a7052d8e2879da6173 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Wed, 11 Dec 2024 11:27:18 +0100 Subject: [PATCH 5/6] code formatting --- .../expensify/livemarkdown/RangeSplitter.java | 4 +-- .../livemarkdown/RangeSplitterTest.java | 28 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/android/src/main/java/com/expensify/livemarkdown/RangeSplitter.java b/android/src/main/java/com/expensify/livemarkdown/RangeSplitter.java index d96332c2a..f9dd0723c 100644 --- a/android/src/main/java/com/expensify/livemarkdown/RangeSplitter.java +++ b/android/src/main/java/com/expensify/livemarkdown/RangeSplitter.java @@ -25,9 +25,9 @@ public static void splitRangesOnEmojis(List markdownRanges, Strin } // Split range - while(j < emojiRanges.size()){ + while (j < emojiRanges.size()) { MarkdownRange emojiRange = emojiRanges.get(j); - if(emojiRange.getStart() > currentRange.getEnd()) break; + if (emojiRange.getStart() > currentRange.getEnd()) break; if (emojiRange.getStart() >= currentRange.getStart() && emojiRange.getEnd() <= currentRange.getEnd()) { MarkdownRange newRange = new MarkdownRange(currentRange.getType(), currentRange.getStart(), emojiRange.getStart() - currentRange.getStart(), currentRange.getDepth()); diff --git a/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java b/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java index b4bf69e2b..f0050ee5a 100644 --- a/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java +++ b/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java @@ -13,7 +13,7 @@ public class RangeSplitterTest { - private void testRange(MarkdownRange range, int start, int end, String type){ + private void testRange(MarkdownRange range, int start, int end, String type) { assertEquals(start, range.getStart()); assertEquals(end, range.getEnd()); assertEquals(type, range.getType()); @@ -23,7 +23,7 @@ private void testRange(MarkdownRange range, int start, int end, String type){ public void testNoOverlap() { List markdownRanges = new ArrayList<>(); markdownRanges.add(new MarkdownRange("strikethrough", 0, 10, 1)); - markdownRanges.add(new MarkdownRange("emoji", 12, 2,1)); + markdownRanges.add(new MarkdownRange("emoji", 12, 2, 1)); splitRangesOnEmojis(markdownRanges, "strikethrough"); @@ -47,7 +47,7 @@ public void testOverlapWrongType() { } @Test - public void testSingleOverlap(){ + public void testSingleOverlap() { List markdownRanges = new ArrayList<>(); markdownRanges.add(new MarkdownRange("strikethrough", 0, 10, 1)); markdownRanges.add(new MarkdownRange("emoji", 3, 4, 1)); // This should split the strikethrough range @@ -58,13 +58,13 @@ public void testSingleOverlap(){ Collections.sort(markdownRanges, (r1, r2) -> Integer.compare(r1.getStart(), r2.getStart())); assertEquals(3, markdownRanges.size()); - testRange(markdownRanges.get(0), 0 ,3, "strikethrough"); - testRange(markdownRanges.get(1), 3 ,7, "emoji"); - testRange(markdownRanges.get(2), 7 ,10, "strikethrough"); + testRange(markdownRanges.get(0), 0, 3, "strikethrough"); + testRange(markdownRanges.get(1), 3, 7, "emoji"); + testRange(markdownRanges.get(2), 7, 10, "strikethrough"); } @Test - public void testMultipleOverlapsMultipleTypes(){ + public void testMultipleOverlapsMultipleTypes() { List markdownRanges = new ArrayList<>(); markdownRanges.add(new MarkdownRange("italic", 0, 20, 1)); markdownRanges.add(new MarkdownRange("strikethrough", 2, 12, 1)); @@ -78,12 +78,12 @@ public void testMultipleOverlapsMultipleTypes(){ Collections.sort(markdownRanges, (r1, r2) -> Integer.compare(r1.getStart(), r2.getStart())); assertEquals(7, markdownRanges.size()); - testRange(markdownRanges.get(0), 0 ,20, "italic"); - testRange(markdownRanges.get(1), 2 ,3, "strikethrough"); - testRange(markdownRanges.get(2), 3 ,4, "emoji"); - testRange(markdownRanges.get(3), 4 , 8, "strikethrough"); - testRange(markdownRanges.get(4), 8 ,10, "emoji"); - testRange(markdownRanges.get(5), 10 ,14, "strikethrough"); - testRange(markdownRanges.get(6), 22 ,27, "strikethrough"); + testRange(markdownRanges.get(0), 0, 20, "italic"); + testRange(markdownRanges.get(1), 2, 3, "strikethrough"); + testRange(markdownRanges.get(2), 3, 4, "emoji"); + testRange(markdownRanges.get(3), 4, 8, "strikethrough"); + testRange(markdownRanges.get(4), 8, 10, "emoji"); + testRange(markdownRanges.get(5), 10, 14, "strikethrough"); + testRange(markdownRanges.get(6), 22, 27, "strikethrough"); } } From b39723febdc51e58728ae5fac258392749fa9f50 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Thu, 12 Dec 2024 18:13:59 +0100 Subject: [PATCH 6/6] review suggestions --- android/build.gradle | 2 +- .../livemarkdown/MarkdownParser.java | 4 +- .../expensify/livemarkdown/MarkdownRange.java | 28 +++++++++++ .../expensify/livemarkdown/RangeSplitter.java | 33 ++++++++----- .../livemarkdown/RangeSplitterTest.java | 48 ++++++++----------- 5 files changed, 72 insertions(+), 43 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index a57fa2c40..3ba26f751 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -176,7 +176,7 @@ dependencies { implementation "com.facebook.react:hermes-android" // version substituted by RNGP implementation project(":react-native-reanimated") - testImplementation 'junit:junit:4.13.2' + testImplementation "junit:junit:4.13.2" } if (isNewArchitectureEnabled()) { diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownParser.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownParser.java index 24a165eff..791c4f2bc 100644 --- a/android/src/main/java/com/expensify/livemarkdown/MarkdownParser.java +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownParser.java @@ -54,8 +54,8 @@ private List parseRanges(String rangesJSON, String innerText) { } catch (JSONException e) { return Collections.emptyList(); } - splitRangesOnEmojis(markdownRanges, "italic"); - splitRangesOnEmojis(markdownRanges, "strikethrough"); + markdownRanges = splitRangesOnEmojis(markdownRanges, "italic"); + markdownRanges = splitRangesOnEmojis(markdownRanges, "strikethrough"); return markdownRanges; } public synchronized List parse(@NonNull String text, int parserId) { diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownRange.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownRange.java index 1fda115b9..479f5fa11 100644 --- a/android/src/main/java/com/expensify/livemarkdown/MarkdownRange.java +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownRange.java @@ -36,4 +36,32 @@ public int getLength() { public int getDepth() { return mDepth; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o instanceof MarkdownRange other) { + return this.mType.equals(other.mType) + && this.mStart == other.mStart + && this.mEnd == other.mEnd + && this.mLength == other.mLength + && this.mDepth == other.mDepth; + } + return false; + } + + @NonNull + @Override + public String toString() { + return "MarkdownRange{" + + "type='" + mType + "'" + + ", start=" + mStart + + ", end=" + mEnd + + ", length=" + mLength + + ", depth=" + mDepth + + "}"; + } } diff --git a/android/src/main/java/com/expensify/livemarkdown/RangeSplitter.java b/android/src/main/java/com/expensify/livemarkdown/RangeSplitter.java index f9dd0723c..9212bbfda 100644 --- a/android/src/main/java/com/expensify/livemarkdown/RangeSplitter.java +++ b/android/src/main/java/com/expensify/livemarkdown/RangeSplitter.java @@ -1,13 +1,15 @@ package com.expensify.livemarkdown; +import androidx.annotation.NonNull; + import java.util.ArrayList; import java.util.List; public class RangeSplitter { - public static void splitRangesOnEmojis(List markdownRanges, String type) { - List emojiRanges = new ArrayList<>(); - List oldRanges = new ArrayList<>(markdownRanges); - markdownRanges.clear(); + public static ArrayList splitRangesOnEmojis(@NonNull List markdownRanges, @NonNull String type) { + ArrayList emojiRanges = new ArrayList<>(); + ArrayList oldRanges = new ArrayList<>(markdownRanges); + ArrayList newRanges = new ArrayList<>(); for (MarkdownRange range : oldRanges) { if (range.getType().equals("emoji")) { emojiRanges.add(range); @@ -19,26 +21,33 @@ public static void splitRangesOnEmojis(List markdownRanges, Strin while (i < oldRanges.size()) { MarkdownRange currentRange = oldRanges.get(i); if (!currentRange.getType().equals(type)) { - markdownRanges.add(currentRange); + newRanges.add(currentRange); i += 1; continue; } - // Split range + // Iterate through all emoji ranges before the end of the current range, splitting the current range at each intersection. while (j < emojiRanges.size()) { MarkdownRange emojiRange = emojiRanges.get(j); - if (emojiRange.getStart() > currentRange.getEnd()) break; + if (emojiRange.getStart() > currentRange.getEnd()) { + break; + } - if (emojiRange.getStart() >= currentRange.getStart() && emojiRange.getEnd() <= currentRange.getEnd()) { - MarkdownRange newRange = new MarkdownRange(currentRange.getType(), currentRange.getStart(), emojiRange.getStart() - currentRange.getStart(), currentRange.getDepth()); - currentRange = new MarkdownRange(currentRange.getType(), emojiRange.getEnd(), currentRange.getEnd() - emojiRange.getEnd(), currentRange.getDepth()); + int currentStart = currentRange.getStart(); + int currentEnd = currentRange.getEnd(); + int emojiStart = emojiRange.getStart(); + int emojiEnd = emojiRange.getEnd(); + if (emojiStart >= currentStart && emojiEnd <= currentEnd) { // Intersection + MarkdownRange newRange = new MarkdownRange(currentRange.getType(), currentStart, emojiStart - currentStart, currentRange.getDepth()); + currentRange = new MarkdownRange(currentRange.getType(), emojiEnd, currentEnd - emojiEnd, currentRange.getDepth()); - markdownRanges.add(newRange); + newRanges.add(newRange); } j += 1; } - markdownRanges.add(currentRange); + newRanges.add(currentRange); i += 1; } + return newRanges; } } diff --git a/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java b/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java index f0050ee5a..48f0a3185 100644 --- a/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java +++ b/android/src/test/java/com/expensify/livemarkdown/RangeSplitterTest.java @@ -2,7 +2,6 @@ import static com.expensify.livemarkdown.RangeSplitter.splitRangesOnEmojis; - import static org.junit.Assert.assertEquals; import org.junit.Test; @@ -13,54 +12,47 @@ public class RangeSplitterTest { - private void testRange(MarkdownRange range, int start, int end, String type) { - assertEquals(start, range.getStart()); - assertEquals(end, range.getEnd()); - assertEquals(type, range.getType()); - } - @Test public void testNoOverlap() { List markdownRanges = new ArrayList<>(); markdownRanges.add(new MarkdownRange("strikethrough", 0, 10, 1)); markdownRanges.add(new MarkdownRange("emoji", 12, 2, 1)); - splitRangesOnEmojis(markdownRanges, "strikethrough"); + markdownRanges = splitRangesOnEmojis(markdownRanges, "strikethrough"); assertEquals(2, markdownRanges.size()); - - testRange(markdownRanges.get(0), 0, 10, "strikethrough"); - testRange(markdownRanges.get(1), 12, 14, "emoji"); + assertEquals(new MarkdownRange("strikethrough", 0, 10, 1), markdownRanges.get(0)); + assertEquals(new MarkdownRange("emoji", 12, 2, 1), markdownRanges.get(1)); } @Test - public void testOverlapWrongType() { + public void testOverlapDifferentType() { List markdownRanges = new ArrayList<>(); markdownRanges.add(new MarkdownRange("strikethrough", 0, 10, 1)); markdownRanges.add(new MarkdownRange("emoji", 3, 4, 1)); - splitRangesOnEmojis(markdownRanges, "italic"); + markdownRanges = splitRangesOnEmojis(markdownRanges, "italic"); assertEquals(2, markdownRanges.size()); - testRange(markdownRanges.get(0), 0, 10, "strikethrough"); - testRange(markdownRanges.get(1), 3, 7, "emoji"); + assertEquals(new MarkdownRange("strikethrough", 0, 10, 1), markdownRanges.get(0)); + assertEquals(new MarkdownRange("emoji", 3, 4, 1), markdownRanges.get(1)); } @Test public void testSingleOverlap() { List markdownRanges = new ArrayList<>(); markdownRanges.add(new MarkdownRange("strikethrough", 0, 10, 1)); - markdownRanges.add(new MarkdownRange("emoji", 3, 4, 1)); // This should split the strikethrough range + markdownRanges.add(new MarkdownRange("emoji", 3, 4, 1)); // This range should split the strikethrough range - splitRangesOnEmojis(markdownRanges, "strikethrough"); + markdownRanges = splitRangesOnEmojis(markdownRanges, "strikethrough"); // Sort is needed because ranges may get mixed while splitting Collections.sort(markdownRanges, (r1, r2) -> Integer.compare(r1.getStart(), r2.getStart())); assertEquals(3, markdownRanges.size()); - testRange(markdownRanges.get(0), 0, 3, "strikethrough"); - testRange(markdownRanges.get(1), 3, 7, "emoji"); - testRange(markdownRanges.get(2), 7, 10, "strikethrough"); + assertEquals(new MarkdownRange("strikethrough", 0, 3, 1), markdownRanges.get(0)); + assertEquals(new MarkdownRange("emoji", 3, 4, 1), markdownRanges.get(1)); + assertEquals(new MarkdownRange("strikethrough", 7, 3, 1), markdownRanges.get(2)); } @Test @@ -72,18 +64,18 @@ public void testMultipleOverlapsMultipleTypes() { markdownRanges.add(new MarkdownRange("emoji", 8, 2, 1)); markdownRanges.add(new MarkdownRange("strikethrough", 22, 5, 1)); - splitRangesOnEmojis(markdownRanges, "strikethrough"); + markdownRanges = splitRangesOnEmojis(markdownRanges, "strikethrough"); // Sort is needed because ranges may get mixed while splitting Collections.sort(markdownRanges, (r1, r2) -> Integer.compare(r1.getStart(), r2.getStart())); assertEquals(7, markdownRanges.size()); - testRange(markdownRanges.get(0), 0, 20, "italic"); - testRange(markdownRanges.get(1), 2, 3, "strikethrough"); - testRange(markdownRanges.get(2), 3, 4, "emoji"); - testRange(markdownRanges.get(3), 4, 8, "strikethrough"); - testRange(markdownRanges.get(4), 8, 10, "emoji"); - testRange(markdownRanges.get(5), 10, 14, "strikethrough"); - testRange(markdownRanges.get(6), 22, 27, "strikethrough"); + assertEquals(new MarkdownRange("italic", 0, 20, 1), markdownRanges.get(0)); + assertEquals(new MarkdownRange("strikethrough", 2, 1, 1), markdownRanges.get(1)); + assertEquals(new MarkdownRange("emoji", 3, 1, 1), markdownRanges.get(2)); + assertEquals(new MarkdownRange("strikethrough", 4, 4, 1), markdownRanges.get(3)); + assertEquals(new MarkdownRange("emoji", 8, 2, 1), markdownRanges.get(4)); + assertEquals(new MarkdownRange("strikethrough", 10, 4, 1), markdownRanges.get(5)); + assertEquals(new MarkdownRange("strikethrough", 22, 5, 1), markdownRanges.get(6)); } }