feat: 2.22 ollama models blobs comment from manifests | ollama models 文件夹从 manifests 获取 blobs 文件注释

This commit is contained in:
林万程
2025-02-21 07:38:15 +08:00
parent d6d7d85c5a
commit 2d3f8d17de
9 changed files with 176 additions and 76 deletions

View File

@@ -3,6 +3,7 @@ package io.github.linwancen.plugin.show.ext;
import com.intellij.ide.projectView.ProjectViewNode;
import com.intellij.openapi.vfs.VirtualFile;
import io.github.linwancen.plugin.show.ext.conf.ConfCache;
import io.github.linwancen.plugin.show.ext.listener.FileLoader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -29,9 +30,16 @@ public class TreeExt {
file.getNameWithoutExtension(),
};
@Nullable String extDoc = GetFromDocMap.get(docMap, words);
if (extDoc == null) {
return null;
if (extDoc != null) {
return " " + extDoc;
}
return " " + extDoc;
@NotNull List<FileLoader> fileLoaders = FileLoader.EPN.getExtensionList();
for (@NotNull FileLoader fileLoader : fileLoaders) {
@Nullable String s = fileLoader.treeDoc(file);
if (s != null) {
return s;
}
}
return null;
}
}

View File

@@ -5,10 +5,15 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileVisitor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* ExtensionPointName: fileLoader
*/
@@ -17,14 +22,35 @@ public abstract class FileLoader {
public static final ExtensionPointName<FileLoader> EPN =
ExtensionPointName.create("io.github.linwancen.show-comment.fileLoader");
public abstract void clearAll();
public final Map<VirtualFile, String> fileDoc = new ConcurrentHashMap<>();
@Nullable
public String treeDoc(@Nullable VirtualFile virtualFile) {
if (virtualFile == null) {
return null;
}
return fileDoc.get(virtualFile);
}
public void clearAll() {
fileDoc.clear();
}
/**
* not need skipFile(file) skipFile(newFile)
*/
public abstract void copyImpl(@NotNull VirtualFile file, @NotNull VirtualFile newFile);
public void copyImpl(@NotNull VirtualFile file, @NotNull VirtualFile newFile) {
String s = fileDoc.get(file);
if (s != null) {
fileDoc.put(newFile, s);
}
}
public abstract void remove(@NotNull VirtualFile file, @Nullable String oldName);
public void remove(@NotNull VirtualFile file, @Nullable String oldName) {
if (oldName == null) {
fileDoc.remove(file);
}
}
public boolean skipFile(@NotNull VirtualFile file) {
return skipExt(file.getExtension());
@@ -50,13 +76,27 @@ public abstract class FileLoader {
-> loadAllImpl(project)));
}
public void visitChildrenRecursively(@NotNull Project project, @NotNull VirtualFile dir, @NotNull StringBuilder sb) {
VfsUtil.visitChildrenRecursively(dir, new VirtualFileVisitor<Void>() {
@Override
public boolean visitFile(@NotNull VirtualFile file) {
if (file.isDirectory()) {
return true;
}
loadFileImpl(file, project);
sb.append(file.getPath()).append("\n");
return true;
}
});
}
void loadFile(@NotNull VirtualFile file, @Nullable Project project) {
if (skipFile(file)) return;
if (project != null && DumbService.isDumb(project)) return;
ApplicationManager.getApplication().executeOnPooledThread(() ->
ApplicationManager.getApplication().runReadAction(() -> {
loadFileImpl(file, project);
if (!project.isDisposed()) {
if (project != null && !project.isDisposed()) {
ProjectView.getInstance(project).refresh();
}
}));

View File

@@ -0,0 +1,103 @@
package io.github.linwancen.plugin.show.ext.ollama;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import io.github.linwancen.plugin.show.ext.listener.FileLoader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
/**
* Open Ollama models dir
*/
public class OllamaModelsCache extends FileLoader {
private static final Logger LOG = LoggerFactory.getLogger(OllamaModelsCache.class);
@Override
public boolean skipFile(@NotNull VirtualFile file) {
return !file.getPath().contains("/manifests/registry.ollama.ai");
}
@Override
public void loadAllImpl(@NotNull Project project) {
LocalFileSystem fileSystem = LocalFileSystem.getInstance();
@Nullable VirtualFile dir = fileSystem.findFileByPath(project.getBasePath() + "/manifests/registry.ollama.ai");
if (dir == null) {
return;
}
@NotNull StringBuilder sb = new StringBuilder();
visitChildrenRecursively(project, dir, sb);
if (!project.isDisposed()) {
ProjectView.getInstance(project).refresh();
}
LOG.info("ollama manifests load all complete files\n{}", sb);
}
@Override
public void loadFileImpl(@NotNull VirtualFile file, @Nullable Project project) {
if (project == null) {
return;
}
try {
VirtualFile parent = file.getParent();
if (parent == null) {
return;
}
@NotNull String name = parent.getName();
@NotNull String version = file.getName();
@NotNull String id = name + ':' + version;
@NotNull String s = new String(file.contentsToByteArray(), file.getCharset());
JsonElement jsonElement = JsonParser.parseString(s);
if (jsonElement == null || !jsonElement.isJsonObject()) {
return;
}
JsonObject json = jsonElement.getAsJsonObject();
JsonObject config = json.getAsJsonObject("config");
load(project, config, id);
JsonArray layers = json.getAsJsonArray("layers");
if (layers == null) {
return;
}
layers.forEach(layer -> load(project, layer.getAsJsonObject(), id));
} catch (IOException e) {
LOG.warn("ollama manifests load {} fail: ", file.getPath(), e);
}
}
private void load(@NotNull Project project, @Nullable JsonObject config, String id) {
if (config == null) {
return;
}
JsonElement digest = config.get("digest");
if (digest == null) {
return;
}
@NotNull String fileName = digest.getAsString().replace(':', '-');
LocalFileSystem fileSystem = LocalFileSystem.getInstance();
@Nullable VirtualFile file = fileSystem.findFileByPath(project.getBasePath() + "/blobs/" + fileName);
if (file == null) {
return;
}
JsonElement mediaType = config.get("mediaType");
if (mediaType == null) {
fileDoc.put(file, id);
return;
}
String type = mediaType.getAsString();
if (type.endsWith("json")) {
type = type.substring(0, type.lastIndexOf('.'));
}
@NotNull String typeEnd = type.substring(type.lastIndexOf('.') + 1);
fileDoc.put(file, id + " | " + typeEnd);
}
}

View File

@@ -1,21 +1,16 @@
package io.github.linwancen.plugin.show.lang;
import com.intellij.ide.projectView.ProjectViewNode;
import com.intellij.lang.html.HTMLLanguage;
import com.intellij.lang.javascript.psi.JSPsiReferenceElement;
import com.intellij.model.psi.PsiSymbolReference;
import com.intellij.model.psi.PsiSymbolReferenceService;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import io.github.linwancen.plugin.show.bean.LineInfo;
import io.github.linwancen.plugin.show.bean.SettingsInfo;
import io.github.linwancen.plugin.show.lang.base.DocFilter;
import io.github.linwancen.plugin.show.lang.base.DocSkip;
import io.github.linwancen.plugin.show.lang.vue.VueRouterCache;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@@ -60,17 +55,6 @@ public class HtmlLangDoc extends JsLangDoc {
return info.appSettings.showLineEndCommentJs || info.appSettings.showLineEndCommentHtml;
}
@Override
public @Nullable <T extends SettingsInfo> String treeDoc(@NotNull T info, @NotNull ProjectViewNode<?> node,
@NotNull Project project) {
@Nullable VirtualFile virtualFile = node.getVirtualFile();
@Nullable String doc = VueRouterCache.fileDoc(virtualFile);
if (doc != null) {
return doc;
}
return super.treeDoc(info, node, project);
}
/**
* Override like Java/Json/Html
*/
@@ -80,7 +64,7 @@ public class HtmlLangDoc extends JsLangDoc {
if (DocSkip.skipTagAttr(info, ref)) {
return null;
}
if (WEB_DOC_METHOD == null || !info.appSettings.showLineEndCommentHtml) {
if (WEB_DOC_METHOD == null || REF_METHOD == null || !info.appSettings.showLineEndCommentHtml) {
return super.refDoc(info, ref);
}
@NotNull PsiSymbolReferenceService service = PsiSymbolReferenceService.getService();

View File

@@ -14,6 +14,7 @@ import com.intellij.psi.PsiManager;
import com.intellij.psi.util.PsiTreeUtil;
import io.github.linwancen.plugin.show.bean.LineInfo;
import io.github.linwancen.plugin.show.bean.SettingsInfo;
import io.github.linwancen.plugin.show.ext.listener.FileLoader;
import io.github.linwancen.plugin.show.lang.base.BaseLangDoc;
import io.github.linwancen.plugin.show.lang.vue.VueRouterCache;
import org.jetbrains.annotations.NotNull;
@@ -57,7 +58,10 @@ public class JsLangDoc extends BaseLangDoc {
if (doc != null && "index".equals(virtualFile.getNameWithoutExtension())) {
VirtualFile parent = virtualFile.getParent();
if (parent != null) {
VueRouterCache.DOC_CACHE.put(parent, doc);
@Nullable VueRouterCache extension = FileLoader.EPN.findExtension(VueRouterCache.class);
if (extension != null) {
extension.fileDoc.put(parent, doc);
}
}
}
return doc;

View File

@@ -11,9 +11,7 @@ import com.intellij.lang.javascript.psi.JSObjectLiteralExpression;
import com.intellij.lang.javascript.psi.JSProperty;
import com.intellij.lang.javascript.psi.JSReferenceExpression;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileVisitor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
@@ -29,51 +27,19 @@ import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* call ConfFactory, ConfCacheGetUtils
* Usage HtmlLangDoc, JSLangDoc
*/
public class VueRouterCache extends FileLoader {
private static final Logger LOG = LoggerFactory.getLogger(VueRouterCache.class);
public static final Map<VirtualFile, String> DOC_CACHE = new ConcurrentHashMap<>();
@Nullable
public static String fileDoc(@Nullable VirtualFile virtualFile) {
if (virtualFile == null) {
return null;
}
return DOC_CACHE.get(virtualFile);
}
@Override
public void clearAll() {
DOC_CACHE.clear();
}
@Override
public void remove(@NotNull VirtualFile file, @Nullable String oldName) {
if (oldName == null) {
DOC_CACHE.remove(file);
}
}
@Override
public boolean skipFile(@NotNull VirtualFile file) {
@Nullable String ext = file.getExtension();
return !file.getPath().contains("src/router") && !"js".equals(ext) && !"ts".equals(ext);
}
@Override
public void copyImpl(@NotNull VirtualFile file, @NotNull VirtualFile newFile) {
String s = DOC_CACHE.get(file);
if (s != null) {
DOC_CACHE.put(newFile, s);
}
}
@Override
public void loadAllImpl(@NotNull Project project) {
@NotNull Collection<VirtualFile> files = FilenameIndex.getVirtualFilesByName(project,
@@ -92,17 +58,7 @@ public class VueRouterCache extends FileLoader {
if (router == null) {
continue;
}
VfsUtil.visitChildrenRecursively(router, new VirtualFileVisitor<Void>() {
@Override
public boolean visitFile(@NotNull VirtualFile file) {
if (file.isDirectory()) {
return super.visitFile(file);
}
loadFileImpl(file, project);
sb.append(file.getPath()).append("\n");
return super.visitFile(file);
}
});
visitChildrenRecursively(project, router, sb);
}
if (files.isEmpty()) {
return;
@@ -135,7 +91,7 @@ public class VueRouterCache extends FileLoader {
}
@Nullable
private static VirtualFile parseArr(JSArrayLiteralExpression arr) {
private VirtualFile parseArr(JSArrayLiteralExpression arr) {
@Nullable VirtualFile virtualFile = null;
@NotNull List<JSObjectLiteralExpression> list = PsiTreeUtil.getChildrenOfTypeAsList(arr,
JSObjectLiteralExpression.class);
@@ -152,7 +108,7 @@ public class VueRouterCache extends FileLoader {
VirtualFile file = subFile.getParent();
if (file != null && title != null) {
virtualFile = file;
DOC_CACHE.put(virtualFile, title);
fileDoc.put(virtualFile, title);
}
}
}
@@ -161,10 +117,10 @@ public class VueRouterCache extends FileLoader {
@Nullable VirtualFile file = parseComponent(obj);
if (file != null) {
virtualFile = file;
DOC_CACHE.put(virtualFile, title);
fileDoc.put(virtualFile, title);
if ("index.vue".equals(virtualFile.getName())) {
virtualFile = virtualFile.getParent();
DOC_CACHE.put(virtualFile, title);
fileDoc.put(virtualFile, title);
}
}
}

View File

@@ -167,6 +167,7 @@ Show doc comment in the Project view Tree, line End, json, other
</extensionPoints>
<extensions defaultExtensionNs="io.github.linwancen.show-comment">
<fileLoader implementation="io.github.linwancen.plugin.show.ext.conf.ConfCache"/>
<fileLoader implementation="io.github.linwancen.plugin.show.ext.ollama.OllamaModelsCache"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">