fix(LineEndCache): insert/delete line load old cache

This commit is contained in:
林万程
2024-01-12 19:44:18 +08:00
parent 48934406bd
commit eaa8540266
4 changed files with 69 additions and 33 deletions

View File

@@ -7,14 +7,16 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class LineInfo extends FileInfo { public class LineInfo extends FileInfo {
public final int lineCount;
public final int lineNumber; public final int lineNumber;
public final int startOffset; public final int startOffset;
public final int endOffset; public final int endOffset;
public final @NotNull String text; public final @NotNull String text;
protected LineInfo(@NotNull FileInfo info, @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); super(info.file, info.document, info.project, FuncEnum.LINE);
this.lineCount = lineCount;
this.lineNumber = lineNumber; this.lineNumber = lineNumber;
this.startOffset = startOffset; this.startOffset = startOffset;
this.endOffset = endOffset; this.endOffset = endOffset;
@@ -30,8 +32,9 @@ public class LineInfo extends FileInfo {
} }
public static @Nullable LineInfo of(@NotNull FileInfo info, int lineNumber) { public static @Nullable LineInfo of(@NotNull FileInfo info, int lineNumber) {
int lineCount = info.document.getLineCount();
// lineNumber start 0, as 1 <= 1 should return // lineNumber start 0, as 1 <= 1 should return
if (info.document.getLineCount() <= lineNumber) { if (lineCount <= lineNumber) {
return null; return null;
} }
try { try {
@@ -41,7 +44,7 @@ public class LineInfo extends FileInfo {
return null; return null;
} }
@NotNull String text = info.document.getText(new TextRange(startOffset, endOffset)); @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) { } catch (Exception e) {
return null; return null;
} }

View File

@@ -3,20 +3,29 @@ package io.github.linwancen.plugin.show.cache;
import com.intellij.openapi.editor.LineExtensionInfo; import com.intellij.openapi.editor.LineExtensionInfo;
import io.github.linwancen.plugin.show.bean.LineInfo; import io.github.linwancen.plugin.show.bean.LineInfo;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class LineEndCache { public class LineEndCache {
@NotNull public volatile String code; @NotNull
@NotNull public final List<LineExtensionInfo> lineExtList = new ArrayList<>(1); public final Map<String, List<LineExtensionInfo>> map = new ConcurrentHashMap<>();
public volatile boolean show = true;
public volatile boolean selectChanged = false; public volatile boolean selectChanged = false;
/** null if updated */ @NotNull
@Nullable public volatile LineInfo info; public volatile LineInfo info;
public LineEndCache(@NotNull String code, @NotNull LineInfo info) { public LineEndCache(@NotNull LineInfo info) {
this.code = code;
this.info = info; this.info = info;
} }
public boolean needUpdate() {
return show && selectChanged;
}
public void updated() {
show = false;
selectChanged = false;
}
} }

View File

@@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -26,18 +27,35 @@ public class LineEndCacheUtils {
public static @Nullable Collection<LineExtensionInfo> get(@NotNull LineInfo info) { public static @Nullable Collection<LineExtensionInfo> get(@NotNull LineInfo info) {
try { try {
@NotNull LineEndCache lineCache = cache @NotNull Map<Integer, LineEndCache> lineMap = cache
.computeIfAbsent(info.project, a -> new ConcurrentHashMap<>()) .computeIfAbsent(info.project, a -> new ConcurrentHashMap<>())
.computeIfAbsent(info.file, a -> new ConcurrentHashMap<>()) .computeIfAbsent(info.file, a -> new ConcurrentHashMap<>());
.computeIfAbsent(info.lineNumber, a -> new LineEndCache(info.text, info)); @NotNull LineEndCache lineCache = lineMap
if (lineCache.selectChanged) { .computeIfAbsent(info.lineNumber, a -> new LineEndCache(info));
lineCache.info = info; @NotNull LineInfo oldInfo = lineCache.info;
} else if (!info.text.equals(lineCache.code)) { lineCache.info = info;
lineCache.info = info; lineCache.show = true;
lineCache.lineExtList.clear();
}
checkScheduleAndInit(); checkScheduleAndInit();
return lineCache.lineExtList; @Nullable List<LineExtensionInfo> 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) { } catch (Throwable e) {
LOG.info("LineEndCacheUtils catch Throwable but log to record.", e); LOG.info("LineEndCacheUtils catch Throwable but log to record.", e);
return null; return null;
@@ -73,27 +91,32 @@ public class LineEndCacheUtils {
if (DumbService.isDumb(project)) { if (DumbService.isDumb(project)) {
return; return;
} }
fileMap.forEach((file, lineMap) -> lineMap.forEach((lineNumber, lineEndCache) -> { fileMap.forEach((file, lineMap) -> lineMap.forEach((lineNumber, lineCache) -> {
if (lineEndCache.info == null) { @NotNull LineInfo info = lineCache.info;
@Nullable List<LineExtensionInfo> list = lineCache.map.get(info.text);
if (!(lineCache.needUpdate() || list == null)) {
return; return;
} }
ApplicationManager.getApplication().runReadAction(() -> { ApplicationManager.getApplication().runReadAction(() -> {
try { try {
@Nullable LineInfo info = lineEndCache.info; @Nullable LineExtensionInfo lineExt = LineEnd.lineExt(info);
if (info == null) { @Nullable LineInfo info2 = LineInfo.of(info, lineNumber);
if (info2 == null || !info2.text.equals(info.text)) {
return; return;
} }
lineEndCache.info = null; if (list != null) {
if (lineEndCache.selectChanged) { list.clear();
lineEndCache.selectChanged = false;
lineEndCache.lineExtList.clear();
} }
@Nullable LineExtensionInfo lineExt = LineEnd.lineExt(info);
if (lineExt != null) { 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 lineCache.updated();
lineEndCache.code = info.text;
} catch (Exception e) { } catch (Exception e) {
LOG.info("LineEndCacheUtils lineMap.forEach catch Throwable but log to record.", e); LOG.info("LineEndCacheUtils lineMap.forEach catch Throwable but log to record.", e);
} }

View File

@@ -46,6 +46,7 @@ public abstract class BaseLangDoc extends EditorLinePainter {
} }
public static @Nullable String langDoc(@NotNull LineInfo info) { 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); @Nullable FileViewProvider viewProvider = PsiManager.getInstance(info.project).findViewProvider(info.file);
if (viewProvider == null) { if (viewProvider == null) {
return null; return null;