From eaa854026642d8b8e4e5ff20b3ed0711ccb048c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E4=B8=87=E7=A8=8B?= <1498425439@qq.com> Date: Fri, 12 Jan 2024 19:44:18 +0800 Subject: [PATCH] fix(LineEndCache): insert/delete line load old cache --- .../linwancen/plugin/show/bean/LineInfo.java | 9 ++- .../plugin/show/cache/LineEndCache.java | 25 ++++--- .../plugin/show/cache/LineEndCacheUtils.java | 67 +++++++++++++------ .../plugin/show/lang/base/BaseLangDoc.java | 1 + 4 files changed, 69 insertions(+), 33 deletions(-) diff --git a/src/main/java/io/github/linwancen/plugin/show/bean/LineInfo.java b/src/main/java/io/github/linwancen/plugin/show/bean/LineInfo.java index 8025b73..fd1b848 100644 --- a/src/main/java/io/github/linwancen/plugin/show/bean/LineInfo.java +++ b/src/main/java/io/github/linwancen/plugin/show/bean/LineInfo.java @@ -7,14 +7,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class LineInfo extends FileInfo { + public final int lineCount; public final int lineNumber; public final int startOffset; public final int endOffset; public final @NotNull String text; protected LineInfo(@NotNull FileInfo info, @NotNull String text, - int lineNumber, int startOffset, int endOffset) { + int lineCount, int lineNumber, int startOffset, int endOffset) { super(info.file, info.document, info.project, FuncEnum.LINE); + this.lineCount = lineCount; this.lineNumber = lineNumber; this.startOffset = startOffset; this.endOffset = endOffset; @@ -30,8 +32,9 @@ public class LineInfo extends FileInfo { } public static @Nullable LineInfo of(@NotNull FileInfo info, int lineNumber) { + int lineCount = info.document.getLineCount(); // lineNumber start 0, as 1 <= 1 should return - if (info.document.getLineCount() <= lineNumber) { + if (lineCount <= lineNumber) { return null; } try { @@ -41,7 +44,7 @@ public class LineInfo extends FileInfo { return null; } @NotNull String text = info.document.getText(new TextRange(startOffset, endOffset)); - return new LineInfo(info, text, lineNumber, startOffset, endOffset); + return new LineInfo(info, text, lineCount, lineNumber, startOffset, endOffset); } catch (Exception e) { return null; } diff --git a/src/main/java/io/github/linwancen/plugin/show/cache/LineEndCache.java b/src/main/java/io/github/linwancen/plugin/show/cache/LineEndCache.java index b6659a6..a6cd45a 100644 --- a/src/main/java/io/github/linwancen/plugin/show/cache/LineEndCache.java +++ b/src/main/java/io/github/linwancen/plugin/show/cache/LineEndCache.java @@ -3,20 +3,29 @@ package io.github.linwancen.plugin.show.cache; import com.intellij.openapi.editor.LineExtensionInfo; import io.github.linwancen.plugin.show.bean.LineInfo; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class LineEndCache { - @NotNull public volatile String code; - @NotNull public final List lineExtList = new ArrayList<>(1); + @NotNull + public final Map> map = new ConcurrentHashMap<>(); + public volatile boolean show = true; public volatile boolean selectChanged = false; - /** null if updated */ - @Nullable public volatile LineInfo info; + @NotNull + public volatile LineInfo info; - public LineEndCache(@NotNull String code, @NotNull LineInfo info) { - this.code = code; + public LineEndCache(@NotNull LineInfo info) { this.info = info; } + + public boolean needUpdate() { + return show && selectChanged; + } + + public void updated() { + show = false; + selectChanged = false; + } } diff --git a/src/main/java/io/github/linwancen/plugin/show/cache/LineEndCacheUtils.java b/src/main/java/io/github/linwancen/plugin/show/cache/LineEndCacheUtils.java index 2dc0f3e..97c0561 100644 --- a/src/main/java/io/github/linwancen/plugin/show/cache/LineEndCacheUtils.java +++ b/src/main/java/io/github/linwancen/plugin/show/cache/LineEndCacheUtils.java @@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -26,18 +27,35 @@ public class LineEndCacheUtils { public static @Nullable Collection get(@NotNull LineInfo info) { try { - @NotNull LineEndCache lineCache = cache + @NotNull Map lineMap = cache .computeIfAbsent(info.project, a -> new ConcurrentHashMap<>()) - .computeIfAbsent(info.file, a -> new ConcurrentHashMap<>()) - .computeIfAbsent(info.lineNumber, a -> new LineEndCache(info.text, info)); - if (lineCache.selectChanged) { - lineCache.info = info; - } else if (!info.text.equals(lineCache.code)) { - lineCache.info = info; - lineCache.lineExtList.clear(); - } + .computeIfAbsent(info.file, a -> new ConcurrentHashMap<>()); + @NotNull LineEndCache lineCache = lineMap + .computeIfAbsent(info.lineNumber, a -> new LineEndCache(info)); + @NotNull LineInfo oldInfo = lineCache.info; + lineCache.info = info; + lineCache.show = true; checkScheduleAndInit(); - return lineCache.lineExtList; + @Nullable List list = lineCache.map.get(info.text); + // load from other line + if (list == null && info.lineCount != oldInfo.lineCount) { + int oldLineNumber = info.lineNumber - info.lineCount + oldInfo.lineCount; + @Nullable LineEndCache oldLineCache = lineMap.get(oldLineNumber); + if (oldLineCache != null) { + list = oldLineCache.map.get(info.text); + if (list != null) { + lineCache.map.put(info.text, list); + } + } + } + if (oldInfo.lineCount == info.lineCount) { + lineCache.map.entrySet().removeIf(it -> !it.getKey().equals(info.text)); + } + if (list == null) { + // because may be updated + list = lineCache.map.get(info.text); + } + return list; } catch (Throwable e) { LOG.info("LineEndCacheUtils catch Throwable but log to record.", e); return null; @@ -73,27 +91,32 @@ public class LineEndCacheUtils { if (DumbService.isDumb(project)) { return; } - fileMap.forEach((file, lineMap) -> lineMap.forEach((lineNumber, lineEndCache) -> { - if (lineEndCache.info == null) { + fileMap.forEach((file, lineMap) -> lineMap.forEach((lineNumber, lineCache) -> { + @NotNull LineInfo info = lineCache.info; + @Nullable List list = lineCache.map.get(info.text); + if (!(lineCache.needUpdate() || list == null)) { return; } ApplicationManager.getApplication().runReadAction(() -> { try { - @Nullable LineInfo info = lineEndCache.info; - if (info == null) { + @Nullable LineExtensionInfo lineExt = LineEnd.lineExt(info); + @Nullable LineInfo info2 = LineInfo.of(info, lineNumber); + if (info2 == null || !info2.text.equals(info.text)) { return; } - lineEndCache.info = null; - if (lineEndCache.selectChanged) { - lineEndCache.selectChanged = false; - lineEndCache.lineExtList.clear(); + if (list != null) { + list.clear(); } - @Nullable LineExtensionInfo lineExt = LineEnd.lineExt(info); if (lineExt != null) { - lineEndCache.lineExtList.add(lineExt); + if (list != null) { + list.add(lineExt); + } else { + lineCache.map.put(info.text, new ArrayList<>() {{ + add(lineExt); + }}); + } } - // change after ext is updated - lineEndCache.code = info.text; + lineCache.updated(); } catch (Exception e) { LOG.info("LineEndCacheUtils lineMap.forEach catch Throwable but log to record.", e); } diff --git a/src/main/java/io/github/linwancen/plugin/show/lang/base/BaseLangDoc.java b/src/main/java/io/github/linwancen/plugin/show/lang/base/BaseLangDoc.java index ffca956..9743139 100644 --- a/src/main/java/io/github/linwancen/plugin/show/lang/base/BaseLangDoc.java +++ b/src/main/java/io/github/linwancen/plugin/show/lang/base/BaseLangDoc.java @@ -46,6 +46,7 @@ public abstract class BaseLangDoc extends EditorLinePainter { } public static @Nullable String langDoc(@NotNull LineInfo info) { + // psiFile.getText() may be not equals document.getText() @Nullable FileViewProvider viewProvider = PsiManager.getInstance(info.project).findViewProvider(info.file); if (viewProvider == null) { return null;