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;
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;
}

View File

@@ -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<LineExtensionInfo> lineExtList = new ArrayList<>(1);
@NotNull
public final Map<String, List<LineExtensionInfo>> 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;
}
}

View File

@@ -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<LineExtensionInfo> get(@NotNull LineInfo info) {
try {
@NotNull LineEndCache lineCache = cache
@NotNull Map<Integer, LineEndCache> 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<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) {
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<LineExtensionInfo> 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);
}

View File

@@ -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;