feat: 2.20 support Vue src/router tree doc | 支持 Vue 路由标题文件树注释
This commit is contained in:
@@ -14,7 +14,7 @@ Show doc comment in the Project view Tree, line End, json, other
|
||||
<ul>
|
||||
<li>Java, Kotlin, Groovy, Scala
|
||||
<li>C/C++/OC, Python, Go, Rust, Ruby
|
||||
<li>JS/TS, PHP, SQL
|
||||
<li>HTML(Vue), JS/TS, PHP, SQL
|
||||
<li>YAML/yml
|
||||
</ul>
|
||||
|
||||
@@ -125,6 +125,7 @@ Show doc comment in the Project view Tree, line End, json, other
|
||||
|
||||
<h2>English Change Notes:</h2>
|
||||
<ul>
|
||||
<li>2.20 Add External Comment support Vue src/router tree doc
|
||||
<li>2.19 ★ line-end-comment support HTML(Vue) Tag/Attr doc since 2022.3.1
|
||||
<li>2.18 Add line-end-comment support injected language like SQL
|
||||
<li>2.17 Add External Comment support *.key.regexp and MyBatis xml demo in Git
|
||||
@@ -173,6 +174,7 @@ Show doc comment in the Project view Tree, line End, json, other
|
||||
|
||||
<h2>中文更新说明:</h2>
|
||||
<ul>
|
||||
<li>2.20 增加 外部注释 支持 Vue 路由标题文件树注释
|
||||
<li>2.19 ★ 行末注释 支持 HTML(Vue) 标签/属性 注释从 2022.3.1 起
|
||||
<li>2.18 增加 行末注释 支持注入语言如 SQL
|
||||
<li>2.17 增加 tsv 注释 支持 *.key.regexp 与 Mybatis xml 示例在 Git
|
||||
|
||||
@@ -4,7 +4,7 @@ plugins {
|
||||
}
|
||||
|
||||
group 'io.github.linwancen'
|
||||
version '2.19.0.' + (new Date().format('yyyy.MM.dd_HH.mm'))
|
||||
version '2.20.0.' + (new Date().format('yyyy.MM.dd_HH.mm'))
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
@@ -95,6 +95,7 @@ patchPluginXml {
|
||||
changeNotes = """
|
||||
<h2>English Change Notes:</h2>
|
||||
<ul>
|
||||
<li>2.20 Add External Comment support Vue src/router tree doc
|
||||
<li>2.19 ★ line-end-comment support HTML(Vue) Tag/Attr doc since 2022.3.1
|
||||
<li>2.18 Add line-end-comment support injected language like SQL
|
||||
<li>2.17 Add External Comment support *.key.regexp and MyBatis xml demo in Git
|
||||
@@ -143,6 +144,7 @@ patchPluginXml {
|
||||
|
||||
<h2>中文更新说明:</h2>
|
||||
<ul>
|
||||
<li>2.20 增加 外部注释 支持 Vue 路由标题文件树注释
|
||||
<li>2.19 ★ 行末注释 支持 HTML(Vue) 标签/属性 注释从 2022.3.1 起
|
||||
<li>2.18 增加 行末注释 支持注入语言如 SQL
|
||||
<li>2.17 增加 tsv 注释 支持 *.key.regexp 与 Mybatis xml 示例在 Git
|
||||
|
||||
@@ -139,6 +139,7 @@ public class LineEndCacheUtils {
|
||||
}
|
||||
}).inSmartMode(project).executeSynchronously();
|
||||
}));
|
||||
} catch (ProcessCanceledException ignored) {
|
||||
} catch (IllegalStateException ignore) {
|
||||
// ignore inSmartMode(project) throw:
|
||||
// @NotNull method com/intellij/openapi/project/impl/ProjectImpl.getEarlyDisposable must not return null
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package io.github.linwancen.plugin.show.ext.conf.action;
|
||||
package io.github.linwancen.plugin.show.ext.action;
|
||||
|
||||
import com.intellij.ide.actions.CopyReferenceAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import io.github.linwancen.plugin.show.ext.conf.ConfCache;
|
||||
import io.github.linwancen.plugin.show.ext.listener.FileLoader;
|
||||
import io.github.linwancen.plugin.show.settings.ShowBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -29,7 +29,7 @@ public class ReloadExtDocAction extends CopyReferenceAction {
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
ConfCache.loadAll(project);
|
||||
FileLoader.EPN.getExtensionList().forEach(fileLoader -> fileLoader.loadAll(project));
|
||||
} catch (Throwable t) {
|
||||
LOG.info("ReloadExtDocAction catch Throwable but log to record.", t);
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package io.github.linwancen.plugin.show.ext.conf.action;
|
||||
package io.github.linwancen.plugin.show.ext.action;
|
||||
|
||||
import com.intellij.ide.actions.CopyReferenceAction;
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import io.github.linwancen.plugin.show.ext.conf.ConfCache;
|
||||
import io.github.linwancen.plugin.show.ext.listener.FileLoader;
|
||||
import io.github.linwancen.plugin.show.settings.ShowBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -28,7 +28,7 @@ public class ResetExtDocAction extends CopyReferenceAction {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
try {
|
||||
ConfCache.clearAll();
|
||||
FileLoader.EPN.getExtensionList().forEach(FileLoader::clearAll);
|
||||
@Nullable Project project = e.getProject();
|
||||
if (project == null) {
|
||||
return;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* call ConfCache clear and loadAll
|
||||
*/
|
||||
package io.github.linwancen.plugin.show.ext.action;
|
||||
@@ -1,11 +1,10 @@
|
||||
package io.github.linwancen.plugin.show.ext.conf;
|
||||
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.search.FilenameIndex;
|
||||
import io.github.linwancen.plugin.show.ext.listener.FileLoader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
@@ -23,7 +22,7 @@ import java.util.regex.Pattern;
|
||||
/**
|
||||
* call ConfFactory, ConfCacheGetUtils
|
||||
*/
|
||||
public class ConfCache {
|
||||
public class ConfCache extends FileLoader {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ConfCache.class);
|
||||
|
||||
static final String KEY_MID_EXT = ".key";
|
||||
@@ -74,7 +73,13 @@ public class ConfCache {
|
||||
return ConfCacheGetUtils.filterPath(JSON_CACHE, path);
|
||||
}
|
||||
|
||||
public static void clearAll() {
|
||||
@Override
|
||||
public boolean skipExt(@Nullable String extension) {
|
||||
return !TsvLoader.EXT.equals(extension) && !TsvLoader.REGEXP_EXT.equals(extension);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAll() {
|
||||
EXT_IN_KEY_CACHE.clear();
|
||||
KEY_CACHE.clear();
|
||||
DOC_CACHE.clear();
|
||||
@@ -82,11 +87,15 @@ public class ConfCache {
|
||||
JSON_CACHE.clear();
|
||||
}
|
||||
|
||||
public static void remove(@NotNull VirtualFile file, @Nullable String name) {
|
||||
@Override
|
||||
public void remove(@NotNull VirtualFile file, @Nullable String name) {
|
||||
if (name != null) {
|
||||
int i = name.lastIndexOf('.');
|
||||
@NotNull String ext = name.substring(i + 1);
|
||||
if (skipExt(ext)) return;
|
||||
name = name.substring(0, i);
|
||||
} else {
|
||||
if (skipExt(file.getExtension())) return;
|
||||
name = file.getNameWithoutExtension();
|
||||
}
|
||||
if (name.endsWith(KEY_MID_EXT)) {
|
||||
@@ -100,8 +109,9 @@ public class ConfCache {
|
||||
}
|
||||
}
|
||||
|
||||
public static void copy(@NotNull VirtualFile file, @NotNull VirtualFile newFile) {
|
||||
@NotNull String name = file.getNameWithoutExtension();
|
||||
@Override
|
||||
public void copyImpl(@NotNull VirtualFile file, @NotNull VirtualFile newFile) {
|
||||
@NotNull String name = newFile.getNameWithoutExtension();
|
||||
if (name.endsWith(KEY_MID_EXT)) {
|
||||
copyCache(file, newFile, KEY_CACHE);
|
||||
} else if (name.endsWith(DOC_MID_EXT)) {
|
||||
@@ -121,46 +131,32 @@ public class ConfCache {
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadAll(@NotNull Project project) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() ->
|
||||
DumbService.getInstance(project).runReadActionInSmartMode(() ->
|
||||
ApplicationManager.getApplication().runReadAction(() -> {
|
||||
@NotNull Collection<VirtualFile> files = FilenameIndex.getAllFilesByExt(project,
|
||||
TsvLoader.EXT);
|
||||
@NotNull StringBuilder sb = new StringBuilder();
|
||||
for (@NotNull VirtualFile file : files) {
|
||||
load(file);
|
||||
sb.append(file.getName()).append("\n");
|
||||
}
|
||||
@NotNull Collection<VirtualFile> files2 = FilenameIndex.getAllFilesByExt(project,
|
||||
TsvLoader.REGEXP_EXT);
|
||||
for (@NotNull VirtualFile file : files2) {
|
||||
load(file);
|
||||
sb.append(file.getName()).append("\n");
|
||||
}
|
||||
if (files.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!project.isDisposed()) {
|
||||
ProjectView.getInstance(project).refresh();
|
||||
}
|
||||
LOG.info("Ext doc conf load all complete {} files\n{}", files.size(), sb);
|
||||
})));
|
||||
}
|
||||
|
||||
public static void loadFile(@NotNull VirtualFile file, @Nullable Project project) {
|
||||
if (!TsvLoader.EXT.equals(file.getExtension()) && !TsvLoader.REGEXP_EXT.equals(file.getExtension())) {
|
||||
@Override
|
||||
public void loadAllImpl(@NotNull Project project) {
|
||||
@NotNull Collection<VirtualFile> files = FilenameIndex.getAllFilesByExt(project,
|
||||
TsvLoader.EXT);
|
||||
@NotNull StringBuilder sb = new StringBuilder();
|
||||
for (@NotNull VirtualFile file : files) {
|
||||
loadFileImpl(file, project);
|
||||
sb.append(file.getName()).append("\n");
|
||||
}
|
||||
@NotNull Collection<VirtualFile> files2 = FilenameIndex.getAllFilesByExt(project,
|
||||
TsvLoader.REGEXP_EXT);
|
||||
for (@NotNull VirtualFile file : files2) {
|
||||
loadFileImpl(file, project);
|
||||
sb.append(file.getPath()).append("\n");
|
||||
}
|
||||
if (files.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
ConfCache.load(file);
|
||||
if (project != null && !project.isDisposed()) {
|
||||
ProjectView.getInstance(project).refresh();
|
||||
}
|
||||
});
|
||||
if (!project.isDisposed()) {
|
||||
ProjectView.getInstance(project).refresh();
|
||||
}
|
||||
LOG.info("Ext doc conf load all complete {} files\n{}", files.size(), sb);
|
||||
}
|
||||
|
||||
private static void load(@NotNull VirtualFile file) {
|
||||
@Override
|
||||
public void loadFileImpl(@NotNull VirtualFile file, @Nullable Project project) {
|
||||
@NotNull String name = file.getNameWithoutExtension();
|
||||
if (name.endsWith(KEY_MID_EXT)) {
|
||||
@NotNull String matchName = name.substring(0, name.length() - KEY_MID_EXT.length());
|
||||
|
||||
@@ -46,7 +46,6 @@ class SpiltKeyWordPatternFactory {
|
||||
}
|
||||
sb.insert(0, "\n");
|
||||
sb.insert(0, path);
|
||||
sb.insert(0, "\n");
|
||||
try {
|
||||
@NotNull Pattern compile = Pattern.compile(regex);
|
||||
PATTERN_CACHE.put(regex, compile);
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* call ConfCache clear and loadAll
|
||||
*/
|
||||
package io.github.linwancen.plugin.show.ext.conf.action;
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* call ConfCache.load etc.
|
||||
*/
|
||||
package io.github.linwancen.plugin.show.ext.conf.listener;
|
||||
@@ -1,10 +1,9 @@
|
||||
package io.github.linwancen.plugin.show.ext.conf.listener;
|
||||
package io.github.linwancen.plugin.show.ext.listener;
|
||||
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.project.ProjectManagerListener;
|
||||
import io.github.linwancen.plugin.show.ext.conf.ConfCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -13,11 +12,11 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* call ConfCache.loadAll
|
||||
* call FileLoader.loadAll
|
||||
*/
|
||||
public class ConfFileInitListener implements DumbService.DumbModeListener, ProjectManagerListener {
|
||||
public class FileLoadInitListener implements DumbService.DumbModeListener, ProjectManagerListener {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ConfFileInitListener.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FileLoadInitListener.class);
|
||||
private static final Map<Project, Boolean> PROJECT_LOAD_MAP = new ConcurrentHashMap<>() {};
|
||||
|
||||
@Override
|
||||
@@ -26,7 +25,7 @@ public class ConfFileInitListener implements DumbService.DumbModeListener, Proje
|
||||
@NotNull Project[] projects = ProjectManager.getInstance().getOpenProjects();
|
||||
for (@NotNull Project project : projects) {
|
||||
PROJECT_LOAD_MAP.computeIfAbsent(project, k -> {
|
||||
ConfCache.loadAll(project);
|
||||
FileLoader.EPN.getExtensionList().forEach(fileLoader -> fileLoader.loadAll(project));
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package io.github.linwancen.plugin.show.ext.listener;
|
||||
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
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.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* ExtensionPointName: fileLoader
|
||||
*/
|
||||
public abstract class FileLoader {
|
||||
|
||||
public static final ExtensionPointName<FileLoader> EPN =
|
||||
ExtensionPointName.create("io.github.linwancen.show-comment.fileLoader");
|
||||
|
||||
public abstract void clearAll();
|
||||
|
||||
/**
|
||||
* not need skipFile(file) skipFile(newFile)
|
||||
*/
|
||||
public abstract void copyImpl(@NotNull VirtualFile file, @NotNull VirtualFile newFile);
|
||||
|
||||
public abstract void remove(@NotNull VirtualFile file, @Nullable String oldName);
|
||||
|
||||
public boolean skipFile(@NotNull VirtualFile file) {
|
||||
return skipExt(file.getExtension());
|
||||
}
|
||||
|
||||
public boolean skipExt(@Nullable String ext) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected because not in runReadAction & executeOnPooledThread
|
||||
*/
|
||||
protected abstract void loadAllImpl(Project project);
|
||||
|
||||
/**
|
||||
* not need skipFile(file)
|
||||
*/
|
||||
protected abstract void loadFileImpl(@NotNull VirtualFile file, @Nullable Project project);
|
||||
|
||||
public void loadAll(@NotNull Project project) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() ->
|
||||
DumbService.getInstance(project).runReadActionInSmartMode(() ->
|
||||
ApplicationManager.getApplication().runReadAction(() ->
|
||||
loadAllImpl(project))));
|
||||
}
|
||||
|
||||
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()) {
|
||||
ProjectView.getInstance(project).refresh();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void copy(@NotNull VirtualFile file, @NotNull VirtualFile newFile) {
|
||||
if (skipFile(file)) return;
|
||||
if (skipFile(newFile)) return;
|
||||
copyImpl(file, newFile);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package io.github.linwancen.plugin.show.ext.conf.listener;
|
||||
package io.github.linwancen.plugin.show.ext.listener;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
@@ -7,7 +7,6 @@ import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileMoveEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent;
|
||||
import io.github.linwancen.plugin.show.ext.conf.ConfCache;
|
||||
import io.github.linwancen.plugin.show.ext.conf.TsvLoader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -17,11 +16,11 @@ import org.slf4j.LoggerFactory;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* call ConfCache.loadFile, copy, remove
|
||||
* call FileLoader.loadFile, copy, remove
|
||||
*/
|
||||
public class ConfFileListener implements BulkFileListener {
|
||||
public class FileOptListener implements BulkFileListener {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ConfFileListener.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FileOptListener.class);
|
||||
|
||||
@Override
|
||||
public void after(@NotNull List<? extends VFileEvent> events) {
|
||||
@@ -35,6 +34,7 @@ public class ConfFileListener implements BulkFileListener {
|
||||
}
|
||||
|
||||
private static void forEvent(@NotNull VFileEvent event) {
|
||||
@NotNull List<FileLoader> list = FileLoader.EPN.getExtensionList();
|
||||
@Nullable VirtualFile file = event.getFile();
|
||||
if (file == null) {
|
||||
return;
|
||||
@@ -46,17 +46,15 @@ public class ConfFileListener implements BulkFileListener {
|
||||
@NotNull VFilePropertyChangeEvent changeEvent = (VFilePropertyChangeEvent) event;
|
||||
if ("name".equals(changeEvent.getPropertyName())) {
|
||||
String oldName = changeEvent.getOldValue().toString();
|
||||
if (oldName.endsWith(TsvLoader.EXT) || oldName.endsWith(TsvLoader.REGEXP_EXT)) {
|
||||
// change cache too complicated so remove
|
||||
ConfCache.remove(file, oldName);
|
||||
}
|
||||
// change cache too complicated so remove
|
||||
list.forEach(fileLoader -> fileLoader.remove(file, oldName));
|
||||
}
|
||||
}
|
||||
if (!TsvLoader.EXT.equals(file.getExtension()) && !TsvLoader.REGEXP_EXT.equals(file.getExtension())) {
|
||||
return;
|
||||
}
|
||||
if (event instanceof VFileDeleteEvent) {
|
||||
ConfCache.remove(file, null);
|
||||
list.forEach(fileLoader -> fileLoader.remove(file, null));
|
||||
return;
|
||||
}
|
||||
if (event instanceof VFileCopyEvent) {
|
||||
@@ -65,15 +63,17 @@ public class ConfFileListener implements BulkFileListener {
|
||||
if (newFile == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ConfCache.copy(file, newFile);
|
||||
} catch (Exception ignored) {
|
||||
// ignore
|
||||
for (@NotNull FileLoader loader : list) {
|
||||
try {
|
||||
loader.copy(file, newFile);
|
||||
} catch (Exception ignored) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// VFileCreateEvent
|
||||
// VFileContentChangeEvent
|
||||
ConfCache.loadFile(file, null);
|
||||
list.forEach(fileLoader -> fileLoader.loadFile(file, null));
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,20 @@
|
||||
package io.github.linwancen.plugin.show.ext.conf.listener;
|
||||
package io.github.linwancen.plugin.show.ext.listener;
|
||||
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import io.github.linwancen.plugin.show.ext.conf.ConfCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* call ConfCache.loadFile
|
||||
* call FileLoader.loadFile
|
||||
*/
|
||||
public class ConfFileChangeListener implements FileEditorManagerListener {
|
||||
public class FileSelectChangeListener implements FileEditorManagerListener {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ConfFileChangeListener.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FileSelectChangeListener.class);
|
||||
|
||||
@Override
|
||||
public void selectionChanged(@NotNull FileEditorManagerEvent event) {
|
||||
@@ -29,7 +28,7 @@ public class ConfFileChangeListener implements FileEditorManagerListener {
|
||||
}
|
||||
if (file.exists()) {
|
||||
try {
|
||||
ConfCache.loadFile(file, project);
|
||||
FileLoader.EPN.getExtensionList().forEach(fileLoader -> fileLoader.loadFile(file, project));
|
||||
} catch (Throwable e) {
|
||||
LOG.info("ConfFileChangeListener catch Throwable but log to record.", e);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Init and listen file change
|
||||
*/
|
||||
package io.github.linwancen.plugin.show.ext.listener;
|
||||
@@ -1,21 +1,27 @@
|
||||
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;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -23,15 +29,17 @@ import java.util.List;
|
||||
public class HtmlLangDoc extends JsLangDoc {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HtmlLangDoc.class);
|
||||
|
||||
@Nullable
|
||||
public static final Method WEB_DOC_METHOD;
|
||||
@Nullable
|
||||
public static final Method REF_METHOD;
|
||||
|
||||
static {
|
||||
LANG_DOC_MAP.put(HTMLLanguage.INSTANCE.getID(), new HtmlLangDoc());
|
||||
Method method = null;
|
||||
Method refMethod = null;
|
||||
@Nullable Method method = null;
|
||||
@Nullable Method refMethod = null;
|
||||
try {
|
||||
Class<?> clazz = Class.forName("com.intellij.webSymbols.WebSymbol");
|
||||
@NotNull Class<?> clazz = Class.forName("com.intellij.webSymbols.WebSymbol");
|
||||
method = clazz.getMethod("getDescription");
|
||||
// noinspection UnstableApiUsage
|
||||
refMethod = PsiSymbolReferenceService.class.getMethod("getReferences", PsiElement.class);
|
||||
@@ -52,6 +60,13 @@ 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();
|
||||
return VueRouterCache.fileDoc(virtualFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override like Java/Json/Html
|
||||
*/
|
||||
@@ -64,19 +79,19 @@ public class HtmlLangDoc extends JsLangDoc {
|
||||
if (WEB_DOC_METHOD == null || !info.appSettings.showLineEndCommentHtml) {
|
||||
return super.refDoc(info, ref);
|
||||
}
|
||||
PsiSymbolReferenceService service = PsiSymbolReferenceService.getService();
|
||||
ArrayList<PsiSymbolReference> references = new ArrayList<>();
|
||||
@NotNull PsiSymbolReferenceService service = PsiSymbolReferenceService.getService();
|
||||
@NotNull ArrayList<PsiSymbolReference> references = new ArrayList<>();
|
||||
try {
|
||||
Object object = REF_METHOD.invoke(service, ref);
|
||||
if (object instanceof Iterable) {
|
||||
Iterable<?> objects = (Iterable<?>) object;
|
||||
@NotNull Iterable<?> objects = (Iterable<?>) object;
|
||||
for (Object o : objects) {
|
||||
if (o instanceof PsiSymbolReference) {
|
||||
references.add(((PsiSymbolReference) o));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ProcessCanceledException ignored) {
|
||||
} catch (ProcessCanceledException | InvocationTargetException ignored) {
|
||||
return super.refDoc(info, ref);
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Web Tag Attr getReferences fail: ", e);
|
||||
|
||||
@@ -31,8 +31,8 @@ public abstract class BaseLangDoc extends EditorLinePainter {
|
||||
static {
|
||||
try {
|
||||
// for 2024.2
|
||||
Class<?> clazz = Class.forName("io.github.linwancen.plugin.show.java.KotlinLangDoc");
|
||||
BaseLangDoc lang = (BaseLangDoc) clazz.getConstructor().newInstance();
|
||||
@NotNull Class<?> clazz = Class.forName("io.github.linwancen.plugin.show.java.KotlinLangDoc");
|
||||
@NotNull BaseLangDoc lang = (BaseLangDoc) clazz.getConstructor().newInstance();
|
||||
LANG_DOC_MAP.put("kotlin", lang);
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
@@ -32,12 +32,12 @@ public class DocSkip {
|
||||
|
||||
public static <T extends SettingsInfo> boolean skipTagAttr(@NotNull T info, @NotNull PsiElement ref) {
|
||||
if (ref instanceof XmlTag) {
|
||||
String text = ((XmlTag) ref).getName();
|
||||
@NotNull String text = ((XmlTag) ref).getName();
|
||||
return skipText(info, text,
|
||||
info.globalSettings.tagInclude, info.globalSettings.tagExclude,
|
||||
info.projectSettings.tagInclude, info.projectSettings.tagExclude);
|
||||
} else if (ref instanceof XmlAttribute) {
|
||||
String text = ((XmlAttribute) ref).getName();
|
||||
@NotNull String text = ((XmlAttribute) ref).getName();
|
||||
return skipText(info, text,
|
||||
info.globalSettings.attrInclude, info.globalSettings.attrExclude,
|
||||
info.projectSettings.attrInclude, info.projectSettings.attrExclude);
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
package io.github.linwancen.plugin.show.lang.vue;
|
||||
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.lang.ecmascript6.psi.ES6ExportDefaultAssignment;
|
||||
import com.intellij.lang.ecmascript6.psi.ES6ImportCall;
|
||||
import com.intellij.lang.ecmascript6.psi.ES6ImportedBinding;
|
||||
import com.intellij.lang.javascript.psi.JSArrayLiteralExpression;
|
||||
import com.intellij.lang.javascript.psi.JSExpression;
|
||||
import com.intellij.lang.javascript.psi.JSLiteralExpression;
|
||||
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;
|
||||
import com.intellij.psi.search.FilenameIndex;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
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.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* call ConfFactory, ConfCacheGetUtils
|
||||
*/
|
||||
public class VueRouterCache extends FileLoader {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(VueRouterCache.class);
|
||||
|
||||
private 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,
|
||||
"package.json", GlobalSearchScope.projectScope(project));
|
||||
@NotNull StringBuilder sb = new StringBuilder();
|
||||
for (@NotNull VirtualFile file : files) {
|
||||
VirtualFile parent = file.getParent();
|
||||
if (parent == null) {
|
||||
continue;
|
||||
}
|
||||
@Nullable VirtualFile src = parent.findChild("src");
|
||||
if (src == null) {
|
||||
continue;
|
||||
}
|
||||
@Nullable VirtualFile router = src.findChild("router");
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (files.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!project.isDisposed()) {
|
||||
ProjectView.getInstance(project).refresh();
|
||||
}
|
||||
LOG.info("Vue Router load all complete {} files\n{}", files.size(), sb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFileImpl(@NotNull VirtualFile file, @Nullable Project project) {
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
@Nullable PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
|
||||
if (psiFile == null) {
|
||||
return;
|
||||
}
|
||||
@Nullable ES6ExportDefaultAssignment export = PsiTreeUtil.findChildOfType(psiFile,
|
||||
ES6ExportDefaultAssignment.class);
|
||||
if (export == null) {
|
||||
return;
|
||||
}
|
||||
@Nullable JSArrayLiteralExpression arr = PsiTreeUtil.findChildOfAnyType(export, JSArrayLiteralExpression.class);
|
||||
if (arr == null) {
|
||||
return;
|
||||
}
|
||||
parseArr(arr);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static VirtualFile parseArr(JSArrayLiteralExpression arr) {
|
||||
@Nullable VirtualFile virtualFile = null;
|
||||
@NotNull List<JSObjectLiteralExpression> list = PsiTreeUtil.getChildrenOfTypeAsList(arr,
|
||||
JSObjectLiteralExpression.class);
|
||||
for (@NotNull JSObjectLiteralExpression obj : list) {
|
||||
@Nullable String title = parseTitle(obj);
|
||||
@Nullable JSProperty children = obj.findProperty("children");
|
||||
if (children != null) {
|
||||
@Nullable JSExpression value = children.getValue();
|
||||
if (value instanceof JSArrayLiteralExpression) {
|
||||
@NotNull JSArrayLiteralExpression childrenArr = (JSArrayLiteralExpression) value;
|
||||
@Nullable VirtualFile subFile = parseArr(childrenArr);
|
||||
// common component dir
|
||||
if (subFile != null) {
|
||||
VirtualFile file = subFile.getParent();
|
||||
if (file != null && title != null) {
|
||||
virtualFile = file;
|
||||
DOC_CACHE.put(virtualFile, title);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (title != null) {
|
||||
VirtualFile file = parseComponent(obj);
|
||||
if (file != null) {
|
||||
virtualFile = file;
|
||||
DOC_CACHE.put(virtualFile, title);
|
||||
if ("index.vue".equals(virtualFile.getName())) {
|
||||
virtualFile = virtualFile.getParent();
|
||||
DOC_CACHE.put(virtualFile, title);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return virtualFile;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String parseTitle(@NotNull JSObjectLiteralExpression obj) {
|
||||
@Nullable JSProperty meta = obj.findProperty("meta");
|
||||
if (meta == null) {
|
||||
return null;
|
||||
}
|
||||
@Nullable JSObjectLiteralExpression metaObj = meta.getObjectLiteralExpressionInitializer();
|
||||
if (metaObj == null) {
|
||||
return null;
|
||||
}
|
||||
@Nullable JSProperty titleProp = metaObj.findProperty("title");
|
||||
if (titleProp == null) {
|
||||
return null;
|
||||
}
|
||||
@Nullable JSExpression value = titleProp.getValue();
|
||||
if (value instanceof JSLiteralExpression) {
|
||||
return ((JSLiteralExpression) value).getStringValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static VirtualFile parseComponent(@NotNull JSObjectLiteralExpression obj) {
|
||||
@Nullable JSProperty component = obj.findProperty("component");
|
||||
if (component == null) {
|
||||
return null;
|
||||
}
|
||||
@Nullable PsiElement value = component.getValue();
|
||||
if (value instanceof JSReferenceExpression) {
|
||||
@NotNull JSReferenceExpression ref = (JSReferenceExpression) value;
|
||||
@Nullable PsiElement resolve;
|
||||
try {
|
||||
resolve = ref.resolve();
|
||||
} catch (Throwable ignored) {
|
||||
return null;
|
||||
}
|
||||
// import A from ""
|
||||
if (resolve instanceof ES6ImportedBinding) {
|
||||
@NotNull ES6ImportedBinding binding = (ES6ImportedBinding) resolve;
|
||||
@NotNull Collection<PsiElement> elements = binding.findReferencedElements();
|
||||
for (@NotNull PsiElement element : elements) {
|
||||
if (element instanceof PsiFile) {
|
||||
return ((PsiFile) element).getVirtualFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
// A = () => import('')
|
||||
value = resolve;
|
||||
}
|
||||
// () => import("")
|
||||
@Nullable ES6ImportCall importCall = PsiTreeUtil.findChildOfType(value, ES6ImportCall.class);
|
||||
if (importCall == null) {
|
||||
return null;
|
||||
}
|
||||
@NotNull Collection<PsiElement> elements = importCall.resolveReferencedElements();
|
||||
for (PsiElement element : elements) {
|
||||
PsiFile psiFile = PsiTreeUtil.getParentOfType(element, PsiFile.class);
|
||||
if (psiFile != null) {
|
||||
return psiFile.getVirtualFile();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,8 @@
|
||||
<editor.linePainter implementation="io.github.linwancen.plugin.show.lang.JsLangDoc"/>
|
||||
<editor.linePainter implementation="io.github.linwancen.plugin.show.lang.HtmlLangDoc"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="io.github.linwancen.show-comment">
|
||||
<fileLoader implementation="io.github.linwancen.plugin.show.lang.vue.VueRouterCache"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -12,7 +12,7 @@ Show doc comment in the Project view Tree, line End, json, other
|
||||
<ul>
|
||||
<li>Java, Kotlin, Groovy, Scala
|
||||
<li>C/C++/OC, Python, Go, Rust, Ruby
|
||||
<li>JS/TS, PHP, SQL
|
||||
<li>HTML(Vue), JS/TS, PHP, SQL
|
||||
<li>YAML/yml
|
||||
</ul>
|
||||
|
||||
@@ -145,23 +145,30 @@ Show doc comment in the Project view Tree, line End, json, other
|
||||
</extensions>
|
||||
|
||||
<applicationListeners>
|
||||
<listener class="io.github.linwancen.plugin.show.ext.conf.listener.ConfFileListener"
|
||||
<listener class="io.github.linwancen.plugin.show.ext.listener.FileOptListener"
|
||||
topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/>
|
||||
<listener class="io.github.linwancen.plugin.show.ext.conf.listener.ConfFileChangeListener"
|
||||
<listener class="io.github.linwancen.plugin.show.ext.listener.FileSelectChangeListener"
|
||||
topic="com.intellij.openapi.fileEditor.FileEditorManagerListener"/>
|
||||
<listener class="io.github.linwancen.plugin.show.cache.CacheUpdateEditorListener"
|
||||
topic="com.intellij.openapi.fileEditor.FileEditorManagerListener"/>
|
||||
</applicationListeners>
|
||||
|
||||
<projectListeners>
|
||||
<listener class="io.github.linwancen.plugin.show.ext.conf.listener.ConfFileInitListener"
|
||||
<listener class="io.github.linwancen.plugin.show.ext.listener.FileLoadInitListener"
|
||||
topic="com.intellij.openapi.project.ProjectManagerListener"/>
|
||||
<listener class="io.github.linwancen.plugin.show.ext.conf.listener.ConfFileInitListener"
|
||||
<listener class="io.github.linwancen.plugin.show.ext.listener.FileLoadInitListener"
|
||||
topic="com.intellij.openapi.project.DumbService$DumbModeListener"/>
|
||||
<listener class="io.github.linwancen.plugin.show.cache.CacheUpdateProjectListener"
|
||||
topic="com.intellij.openapi.project.ProjectManagerListener"/>
|
||||
</projectListeners>
|
||||
|
||||
<extensionPoints>
|
||||
<extensionPoint name="fileLoader" dynamic="true" interface="io.github.linwancen.plugin.show.ext.listener.FileLoader"/>
|
||||
</extensionPoints>
|
||||
<extensions defaultExtensionNs="io.github.linwancen.show-comment">
|
||||
<fileLoader implementation="io.github.linwancen.plugin.show.ext.conf.ConfCache"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<editor.linePainter implementation="io.github.linwancen.plugin.show.LineEnd"/>
|
||||
<projectViewNodeDecorator implementation="io.github.linwancen.plugin.show.Tree"/>
|
||||
@@ -189,13 +196,13 @@ Show doc comment in the Project view Tree, line End, json, other
|
||||
<actions>
|
||||
<action
|
||||
id="io.github.linwancen.plugin.show.ext.conf.ReLoadExtDocAction"
|
||||
class="io.github.linwancen.plugin.show.ext.conf.action.ReloadExtDocAction"
|
||||
class="io.github.linwancen.plugin.show.ext.action.ReloadExtDocAction"
|
||||
text="🔄 // Reload External Comment">
|
||||
<add-to-group group-id="ToolsMenu"/>
|
||||
</action>
|
||||
<action
|
||||
id="io.github.linwancen.plugin.show.ext.conf.action.ResetExtDocAction"
|
||||
class="io.github.linwancen.plugin.show.ext.conf.action.ResetExtDocAction"
|
||||
id="io.github.linwancen.plugin.show.ext.action.ResetExtDocAction"
|
||||
class="io.github.linwancen.plugin.show.ext.action.ResetExtDocAction"
|
||||
text="🆑 // Clear External Comment">
|
||||
<add-to-group group-id="ToolsMenu"/>
|
||||
</action>
|
||||
|
||||
@@ -45,4 +45,7 @@ reload.ext.doc=\uD83D\uDD04 // Reload External Comment
|
||||
reset.ext.doc=\uD83C\uDD91 // Clear External Comment
|
||||
line.end.add=// Add Line Comment
|
||||
line.end.copy=// Copy With Line Comment
|
||||
load.vue.router=Load Vue Router
|
||||
reload.vue.router=\uD83D\uDD04 Reload Vue Router
|
||||
reset.vue.router=\uD83C\uDD91 Clear Vue Router
|
||||
copy.class.method.or.file.line=Copy Class.Method / File:LineNum
|
||||
@@ -45,4 +45,7 @@ reload.ext.doc=\uD83D\uDD04 // \u91CD\u65B0\u8BFB\u53D6\u5916\u90E8\u6CE8\u91CA
|
||||
reset.ext.doc=\uD83C\uDD91 // \u6E05\u7406\u5916\u90E8\u6CE8\u91CA
|
||||
line.end.add=// \u6DFB\u52A0\u81EA\u52A8\u6CE8\u91CA
|
||||
line.end.copy=// \u590D\u5236 \u5E26\u81EA\u52A8\u6CE8\u91CA
|
||||
load.vue.router=\u8BFB\u53D6 Vue Router
|
||||
reload.vue.router=\uD83D\uDD04 \u91CD\u65B0\u8BFB\u53D6 Vue \u8DEF\u7531
|
||||
reset.vue.router=\uD83C\uDD91 \u6E05\u7406 Vue \u8DEF\u7531
|
||||
copy.class.method.or.file.line=\u590D\u5236 \u7C7B.\u65B9\u6CD5 / \u6587\u4EF6:\u884C\u53F7
|
||||
Reference in New Issue
Block a user