templateFiles = new HashSet<>();
114 | for (TemplatePath templatePath : ViewCollector.getPaths(project)) {
115 | // we have a namespace given; ignore all other paths
116 | String namespace = templatePath.getNamespace();
117 | if ((ns == null && namespace != null) || ns != null && !ns.equals(namespace)) {
118 | continue;
119 | }
120 |
121 | VirtualFile viewDir = templatePath.getRelativePath(project);
122 | if (viewDir == null) {
123 | continue;
124 | }
125 |
126 | VirtualFile viewsDir = VfsUtil.findRelativeFile(directory, viewDir);
127 | if (viewsDir != null) {
128 | templateFiles.add(viewsDir);
129 | }
130 | }
131 |
132 | return templateFiles;
133 | }
134 |
135 |
136 | /**
137 | * Try to find directory or file navigation for template name
138 | *
139 | * "foo.bar" => "foo", "bar"
140 | */
141 | @NotNull
142 | public static Collection resolveTemplate(@NotNull Project project, @NotNull String templateName, int offset) {
143 | Set files = new HashSet<>();
144 |
145 | // try to find a path pattern on current offset after path normalization
146 | if (offset > 0 && offset < templateName.length()) {
147 | String templateNameWithCaret = normalizeTemplate(new StringBuilder(templateName).insert(offset, '\u0182').toString()).replace("/", ".");
148 | offset = templateNameWithCaret.indexOf('\u0182');
149 |
150 | int i = StringUtils.strip(templateNameWithCaret.replace(String.valueOf('\u0182'), ""), "/").indexOf(".", offset);
151 | if (i > 0) {
152 | files.addAll(resolveTemplateDirectory(project, templateName.substring(0, i)));
153 | }
154 | }
155 |
156 | // full filepath fallback: "foo/foo.blade.php"
157 | if (files.size() == 0) {
158 | files.addAll(resolveTemplateName(project, templateName));
159 | }
160 |
161 | return files;
162 | }
163 |
164 | /**
165 | * Normalize template path
166 | */
167 | @NotNull
168 | public static String normalizeTemplate(@NotNull String templateName) {
169 | return templateName
170 | .replace("\\", "/")
171 | .replaceAll("/+", "/");
172 | }
173 |
174 |
175 | /**
176 | * "'foobar'"
177 | * "'foobar', []"
178 | */
179 | @Nullable
180 | public static String getParameterFromParameterDirective(@NotNull String content) {
181 | Matcher matcher = Pattern.compile("^\\s*['|\"]([^'\"]+)['|\"]").matcher(content);
182 |
183 | if (matcher.find()) {
184 | return StringUtil.trim(matcher.group(1));
185 | }
186 |
187 | return null;
188 | }
189 |
190 |
191 | /**
192 | * Strip template extension for given template name
193 | *
194 | * "foo_blade.blade.php" => "foo_blade"
195 | * "foo_blade.html.twig" => "foo_blade"
196 | * "foo_blade.php" => "foo_blade"
197 | */
198 | @NotNull
199 | public static String stripTemplateExtensions(@NotNull String filename) {
200 | if (filename.endsWith(".blade.php")) {
201 | filename = filename.substring(0, filename.length() - ".blade.php".length());
202 | } else if (filename.endsWith(".html.twig")) {
203 | filename = filename.substring(0, filename.length() - ".html.twig".length());
204 | } else if (filename.endsWith(".php")) {
205 | filename = filename.substring(0, filename.length() - ".php".length());
206 | }
207 |
208 | return filename;
209 | }
210 |
211 | private static class MyViewRecursiveElementWalkingVisitor extends PsiRecursiveElementWalkingVisitor {
212 | private final Collection> views;
213 |
214 | private MyViewRecursiveElementWalkingVisitor(Collection> views) {
215 | this.views = views;
216 | }
217 |
218 | @Override
219 | public void visitElement(PsiElement element) {
220 |
221 | if (element instanceof MethodReference) {
222 | visitMethodReference((MethodReference) element);
223 | }
224 |
225 | if (element instanceof FunctionReference) {
226 | visitFunctionReference((FunctionReference) element);
227 | }
228 |
229 | super.visitElement(element);
230 | }
231 |
232 | private void visitFunctionReference(FunctionReference functionReference) {
233 |
234 | if (!"view".equals(functionReference.getName())) {
235 | return;
236 | }
237 |
238 | PsiElement[] parameters = functionReference.getParameters();
239 |
240 | if (parameters.length < 1 || !(parameters[0] instanceof StringLiteralExpression)) {
241 | return;
242 | }
243 |
244 | String contents = ((StringLiteralExpression) parameters[0]).getContents();
245 | if (StringUtils.isBlank(contents)) {
246 | return;
247 | }
248 |
249 | views.add(Pair.create(contents, parameters[0]));
250 | }
251 |
252 | private void visitMethodReference(MethodReference methodReference) {
253 |
254 | String methodName = methodReference.getName();
255 | if (!RENDER_METHODS.contains(methodName)) {
256 | return;
257 | }
258 |
259 | PsiElement classReference = methodReference.getFirstChild();
260 | if (!(classReference instanceof ClassReference)) {
261 | return;
262 | }
263 |
264 | if (!"View".equals(((ClassReference) classReference).getName())) {
265 | return;
266 | }
267 |
268 | PsiElement[] parameters = methodReference.getParameters();
269 | if (parameters.length == 0 || !(parameters[0] instanceof StringLiteralExpression)) {
270 | return;
271 | }
272 |
273 | String contents = ((StringLiteralExpression) parameters[0]).getContents();
274 | if (StringUtils.isBlank(contents)) {
275 | return;
276 | }
277 |
278 | views.add(Pair.create(contents, parameters[0]));
279 | }
280 | }
281 |
282 | public static File recursionMatch(File root, String file) {
283 | if (root == null) return null;
284 | File[] files = root.listFiles();
285 | if (files != null)
286 | for (File f : files) {
287 | if (f.isFile()) {
288 | String curPath = f.getAbsolutePath().toLowerCase();
289 | curPath = curPath.replace("\\", "/");
290 | curPath=curPath.substring(0,curPath.lastIndexOf("."));
291 | if (curPath.equals(file.toLowerCase())) {
292 | return f;
293 | }
294 | } else if (f.isDirectory()) {
295 | File res=recursionMatch(f, file);
296 | if(res!=null)
297 | return res;
298 | }
299 | }
300 | return null;
301 | }
302 | }
303 |
--------------------------------------------------------------------------------
/src/pers/fw/tplugin/view/ViewCollector.java:
--------------------------------------------------------------------------------
1 | package pers.fw.tplugin.view;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.JsonIOException;
5 | import com.google.gson.JsonSyntaxException;
6 | import com.intellij.ide.highlighter.HtmlFileType;
7 | import com.intellij.openapi.project.Project;
8 | import com.intellij.openapi.vfs.VfsUtil;
9 | import com.intellij.openapi.vfs.VirtualFile;
10 | import com.intellij.openapi.vfs.VirtualFileVisitor;
11 | import com.intellij.psi.PsiDirectory;
12 | import com.intellij.psi.PsiFile;
13 | import com.intellij.psi.search.FilenameIndex;
14 | import com.intellij.psi.search.GlobalSearchScope;
15 |
16 | import com.intellij.psi.util.CachedValueProvider;
17 | import com.intellij.psi.util.CachedValuesManager;
18 |
19 | import org.apache.commons.lang.StringUtils;
20 | import org.jetbrains.annotations.NotNull;
21 | import org.jetbrains.annotations.Nullable;
22 | import pers.fw.tplugin.util.VfsExUtil;
23 | import pers.fw.tplugin.view.dict.JsonTemplatePaths;
24 | import pers.fw.tplugin.view.dict.TemplatePath;
25 |
26 | import java.util.ArrayList;
27 | import java.util.Arrays;
28 | import java.util.Collection;
29 |
30 | /**
31 | * @author Daniel Espendiller
32 | */
33 | public class ViewCollector {
34 | /**
35 | * Default "view" path based on laravel versions
36 | */
37 | public static String curModule = "";
38 | public static TemplatePath[] DEFAULT_TEMPLATE_PATH;
39 |
40 | @NotNull
41 | public static Collection getPaths(@NotNull Project project) {
42 | return getPaths(project, false, false); //fowModify: true,true->false.false
43 | }
44 |
45 | @NotNull
46 | public static Collection getPaths(@NotNull Project project, boolean includeSettings, boolean includeJson) {
47 | Collection templatePaths = new ArrayList<>(Arrays.asList(DEFAULT_TEMPLATE_PATH));
48 | return templatePaths;
49 | }
50 |
51 | private static void collectIdeJsonBladePaths(@NotNull Project project, @NotNull Collection templatePaths) {
52 | for (PsiFile psiFile : FilenameIndex.getFilesByName(project, "ide-blade.json", GlobalSearchScope.allScope(project))) {
53 | Collection cachedValue = CachedValuesManager.getCachedValue(psiFile, new MyJsonCachedValueProvider(psiFile));
54 | if (cachedValue != null) {
55 | templatePaths.addAll(cachedValue);
56 | }
57 | }
58 | }
59 |
60 | /**
61 | * Visit all templates in project path configuration
62 | */
63 | public static void visitFile(@NotNull Project project, @NotNull ViewVisitor visitor) {
64 | //fowModify
65 | // for(TemplatePath templatePath : getPaths(project)) {
66 | Collection paths = getPaths(project, false, false);
67 | for (TemplatePath templatePath : paths) {
68 | visitTemplatePath(project, templatePath, visitor);
69 | }
70 | }
71 |
72 | /**
73 | * Visit all templates in given path
74 | */
75 | private static void visitTemplatePath(@NotNull Project project, @NotNull TemplatePath templatePath, @NotNull ViewVisitor visitor) {
76 | final VirtualFile templateDir = VfsUtil.findRelativeFile(templatePath.getPath(), project.getBaseDir());
77 | if (templateDir == null) {
78 | return;
79 | }
80 |
81 | VfsUtil.visitChildrenRecursively(templateDir, new VirtualFileVisitor() {
82 | @Override
83 | public boolean visitFile(@NotNull VirtualFile virtualFile) {
84 | // if (virtualFile.isDirectory() || !isTemplateFile(virtualFile)) {
85 | //修改, 不匹配后缀,view下的文件全为视图文件
86 | if (virtualFile.isDirectory()) {
87 | return true;
88 | }
89 |
90 | String filename = VfsUtil.getRelativePath(virtualFile, templateDir, '/');
91 | if (filename == null || !filename.contains("/")) {
92 | return true;
93 | }
94 | //fowModify:
95 | // filename = BladeTemplateUtil.stripTemplateExtensions(filename);
96 | // filename = clearStr(filename);
97 | filename = filename.substring(0, filename.lastIndexOf("."));//去掉后缀
98 | String namespace = templatePath.getNamespace();
99 | if (namespace != null && StringUtils.isNotBlank(namespace)) {
100 | visitor.visit(virtualFile, namespace + "::" + filename);
101 | } else {
102 | visitor.visit(virtualFile, filename);
103 | }
104 |
105 | return true;
106 | }
107 |
108 |
109 | /**
110 | * 清理多余字符,
111 | */
112 | private String clearStr(String filename) {
113 | filename = filename.substring(0, filename.length() - ".html".length());
114 | //如果没有module
115 | String prefix = filename.substring(0, curModule.length());
116 | if (curModule.equals(prefix)) {
117 | int len = filename.length();
118 | filename = filename.substring(curModule.length() + 1, len);
119 | }
120 | return filename;
121 | }
122 |
123 | private boolean isTemplateFile(VirtualFile virtualFile) {
124 | // if(virtualFile.getFileType() == BladeFileType.INSTANCE || virtualFile.getFileType() == PhpFileType.INSTANCE) {
125 | if (virtualFile.getFileType() == HtmlFileType.INSTANCE) {
126 | return true;
127 | }
128 |
129 | String extension = virtualFile.getExtension();
130 | // if (extension != null && (extension.equalsIgnoreCase("php") || extension.equalsIgnoreCase("twig"))) {
131 | if (extension != null && (extension.equalsIgnoreCase("html")
132 | || extension.equalsIgnoreCase("php")
133 | || extension.equalsIgnoreCase("tpl")
134 | )) {
135 | return true;
136 | }
137 |
138 | return false;
139 | }
140 | });
141 | }
142 |
143 | public interface ViewVisitor {
144 | void visit(@NotNull VirtualFile virtualFile, @NotNull String name);
145 | }
146 |
147 | private static class MyJsonCachedValueProvider implements CachedValueProvider> {
148 | private final PsiFile psiFile;
149 |
150 | public MyJsonCachedValueProvider(PsiFile psiFile) {
151 | this.psiFile = psiFile;
152 | }
153 |
154 | @Nullable
155 | @Override
156 | public Result> compute() {
157 |
158 | Collection twigPaths = new ArrayList<>();
159 |
160 | String text = psiFile.getText();
161 | JsonTemplatePaths configJson = null;
162 | try {
163 | configJson = new Gson().fromJson(text, JsonTemplatePaths.class);
164 | } catch (JsonSyntaxException | JsonIOException | IllegalStateException ignored) {
165 | }
166 |
167 | if (configJson == null) {
168 | return Result.create(twigPaths, psiFile, psiFile.getVirtualFile());
169 | }
170 |
171 | Collection namespaces = configJson.getNamespaces();
172 | if (namespaces == null || namespaces.size() == 0) {
173 | return Result.create(twigPaths, psiFile, psiFile.getVirtualFile());
174 | }
175 |
176 | for (JsonTemplatePaths.Path jsonPath : namespaces) {
177 | String path = jsonPath.getPath();
178 | if (path == null) {
179 | path = "";
180 | }
181 |
182 | path = StringUtils.stripStart(path.replace("\\", "/"), "/");
183 | PsiDirectory parent = psiFile.getParent();
184 | if (parent == null) {
185 | continue;
186 | }
187 |
188 | // current directory check and subfolder
189 | VirtualFile twigRoot;
190 | if (path.length() > 0) {
191 | twigRoot = VfsUtil.findRelativeFile(parent.getVirtualFile(), path.split("/"));
192 | } else {
193 | twigRoot = psiFile.getParent().getVirtualFile();
194 | }
195 |
196 | if (twigRoot == null) {
197 | continue;
198 | }
199 |
200 | String relativePath = VfsExUtil.getRelativeProjectPath(psiFile.getProject(), twigRoot);
201 | if (relativePath == null) {
202 | continue;
203 | }
204 |
205 | String namespace = jsonPath.getNamespace();
206 |
207 | String namespacePath = StringUtils.stripStart(relativePath, "/");
208 |
209 | if (StringUtils.isNotBlank(namespace)) {
210 | twigPaths.add(new TemplatePath(namespacePath, namespace, true));
211 | } else {
212 | twigPaths.add(new TemplatePath(namespacePath, true));
213 | }
214 | }
215 |
216 | return Result.create(twigPaths, psiFile, psiFile.getVirtualFile());
217 | }
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/src/pers/fw/tplugin/view/ViewReferences2.java:
--------------------------------------------------------------------------------
1 | package pers.fw.tplugin.view;
2 |
3 | import com.intellij.codeInsight.lookup.LookupElement;
4 | import com.intellij.codeInsight.lookup.LookupElementBuilder;
5 | import com.intellij.lang.Language;
6 | import com.intellij.openapi.application.ApplicationManager;
7 | import com.intellij.openapi.editor.Editor;
8 | import com.intellij.openapi.vfs.VfsUtil;
9 | import com.intellij.openapi.vfs.VirtualFile;
10 | import com.intellij.patterns.PlatformPatterns;
11 | import com.intellij.psi.PsiElement;
12 | import com.jetbrains.php.lang.PhpLanguage;
13 | import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
14 | import org.jetbrains.annotations.NotNull;
15 | import org.jetbrains.annotations.Nullable;
16 | import pers.fw.tplugin.inter.GotoCompletionContributor;
17 | import pers.fw.tplugin.inter.GotoCompletionLanguageRegistrar;
18 | import pers.fw.tplugin.inter.GotoCompletionProvider;
19 | import pers.fw.tplugin.inter.GotoCompletionRegistrarParameter;
20 | import pers.fw.tplugin.util.MethodMatcher;
21 | import pers.fw.tplugin.util.PsiElementUtil;
22 | import pers.fw.tplugin.util.PsiElementUtils;
23 | import pers.fw.tplugin.util.Util;
24 | import pers.fw.tplugin.view.dict.TemplatePath;
25 | import java.io.File;
26 | import java.util.ArrayList;
27 | import java.util.Collection;
28 | import java.util.Collections;
29 |
30 | // view 处理类
31 | public class ViewReferences2 implements GotoCompletionLanguageRegistrar {
32 | private static MethodMatcher.CallToSignature[] VIEWS = new MethodMatcher.CallToSignature[]{
33 | new MethodMatcher.CallToSignature("\\think\\View", "fetch"),
34 | new MethodMatcher.CallToSignature("\\think\\Controller", "fetch"),
35 | new MethodMatcher.CallToSignature("\\think\\Controller", "display"),
36 | };
37 |
38 | @Override
39 | public void register(GotoCompletionRegistrarParameter registrar) {
40 | registrar.register(PlatformPatterns.psiElement(), new GotoCompletionContributor() {
41 | @Nullable
42 | @Override
43 | public GotoCompletionProvider getProvider(@Nullable PsiElement psiElement) {
44 | if (psiElement == null) {// || !LaravelProjectComponent.isEnabled(psiElement)) {
45 | return null;
46 | }
47 |
48 | PsiElement parent = psiElement.getParent();
49 | if (parent != null
50 | && (PsiElementUtil.isFunctionReference(parent, "view", 0) || MethodMatcher.getMatchedSignatureWithDepth(parent, VIEWS) != null)
51 | && handlePath(psiElement)) {
52 | return new ViewDirectiveCompletionProvider(parent);
53 | }
54 | return null;
55 | }
56 | });
57 | }
58 |
59 |
60 | @Override
61 | public boolean support(@NotNull Language language) {
62 | return PhpLanguage.INSTANCE == language;
63 | }
64 |
65 | public boolean handlePath(PsiElement psiElement) {
66 | // todo ensure base dir
67 | // String application = "application";
68 | // String projectPath = psiElement.getProject().getBasePath();//"D:\\project2\\test";
69 | // String currentFilePath = psiElement.getContainingFile().getVirtualFile().getPath(); //"D:\\project2\\test\\application\\index\\controller\\Index.php";
70 | // String[] arr = currentFilePath.replace(projectPath, "").split("/");
71 | // if (arr.length < 4 || !arr[1].equals(application)) {
72 | // return false;
73 | // }
74 | String application = Util.getApplicationDir(psiElement);
75 | // String moduleName = arr[2];
76 | String moduleName = Util.getCurTpModuleName(psiElement);
77 | ViewCollector.DEFAULT_TEMPLATE_PATH = new TemplatePath[]{new TemplatePath(application + "/" + moduleName + "/view", false)};
78 | ViewCollector.curModule = moduleName;
79 | return true;
80 | }
81 |
82 |
83 | private static class ViewDirectiveCompletionProvider extends GotoCompletionProvider {
84 | private ViewDirectiveCompletionProvider(PsiElement element) {
85 | super(element);
86 | }
87 |
88 | @NotNull
89 | @Override
90 | public Collection getLookupElements() {
91 |
92 | final Collection lookupElements = new ArrayList<>();
93 |
94 | ViewCollector.visitFile(getProject(), new ViewCollector.ViewVisitor() {
95 | @Override
96 | public void visit(@NotNull VirtualFile virtualFile, @NotNull String name) {
97 | lookupElements.add(LookupElementBuilder.create(name).withIcon(virtualFile.getFileType().getIcon()));
98 | }
99 | }
100 | );
101 |
102 | // @TODO: no filesystem access in test; fake item
103 | if (ApplicationManager.getApplication().isUnitTestMode()) {
104 | lookupElements.add(LookupElementBuilder.create("test_view"));
105 | }
106 |
107 | return lookupElements;
108 | }
109 |
110 | @NotNull
111 | @Override
112 | public Collection extends PsiElement> getPsiTargets(@NotNull PsiElement psiElement, int offset, @NotNull Editor editor) {
113 | PsiElement stringLiteral = psiElement.getParent();
114 | if (!(stringLiteral instanceof StringLiteralExpression)) {
115 | return Collections.emptyList();
116 | }
117 |
118 | String contents = ((StringLiteralExpression) stringLiteral).getContents();
119 |
120 | String viewDir = getProject().getBaseDir() + Util.getApplicationDir(psiElement) + "/" + Util.getCurTpModuleName(psiElement) + "/" + "view" + "/";
121 | String className = "";
122 | String methodName = "";
123 |
124 | if (contents.contains("/")) { // index/test
125 | String[] split = contents.split("/");
126 | className = split[0];
127 | methodName = contents.substring(className.length() + 1);
128 | } else if ("".equals(contents)) { //
129 | className = Util.getPhpClass(psiElement).getName().toLowerCase();
130 | methodName = Util.getMethod(psiElement).getName();
131 | } else { // test
132 | className = Util.getPhpClass(psiElement).getName().toLowerCase();
133 | methodName = contents;
134 | }
135 |
136 | String dir = viewDir + className;//+ "/" + methodName;
137 | String filePath = viewDir + className + "/" + methodName;
138 | dir = dir.replace("file://", "");
139 | filePath = filePath.replace("file://", "");
140 | File file = new File(dir);
141 | File targetFile = TemplateUtil.recursionMatch(file, filePath);
142 | Collection virFiles = new ArrayList<>();
143 | if (targetFile != null) {
144 | VirtualFile fileByIoFile = VfsUtil.findFileByIoFile(targetFile, false);
145 | virFiles.add(fileByIoFile);
146 | }
147 | Collection targets = new ArrayList<>(PsiElementUtils.convertVirtualFilesToPsiFiles(getProject(), virFiles));
148 |
149 | return targets;
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/src/pers/fw/tplugin/view/dict/JsonTemplatePaths.java:
--------------------------------------------------------------------------------
1 | package pers.fw.tplugin.view.dict;
2 |
3 | import org.jetbrains.annotations.Nullable;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Collection;
7 |
8 | /**
9 | * @author Daniel Espendiller
10 | */
11 | public class JsonTemplatePaths {
12 | @Nullable
13 | private Collection namespaces = new ArrayList<>();
14 |
15 | @Nullable
16 | public Collection getNamespaces() {
17 | return namespaces;
18 | }
19 |
20 | public static class Path {
21 | @Nullable
22 | private String path;
23 |
24 | @Nullable
25 | private String namespace;
26 |
27 | @Nullable
28 | public String getPath() {
29 | return path;
30 | }
31 |
32 | @Nullable
33 | public String getNamespace() {
34 | return namespace;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/pers/fw/tplugin/view/dict/TemplatePath.java:
--------------------------------------------------------------------------------
1 | package pers.fw.tplugin.view.dict;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.openapi.vfs.VfsUtil;
5 | import com.intellij.openapi.vfs.VirtualFile;
6 | import com.intellij.util.xmlb.annotations.Attribute;
7 | import com.intellij.util.xmlb.annotations.Tag;
8 | import org.jetbrains.annotations.NotNull;
9 | import org.jetbrains.annotations.Nullable;
10 |
11 | import java.io.File;
12 |
13 | /**
14 | * @author Daniel Espendiller
15 | */
16 | @Tag("templatePath")
17 | public class TemplatePath {
18 |
19 | private String path;
20 | private boolean customPath = true;
21 |
22 | @Nullable
23 | private String namespace;
24 |
25 | public TemplatePath() {
26 | }
27 |
28 | public TemplatePath(@NotNull String path, boolean customPath) {
29 | this.path = path;
30 | this.customPath = customPath;
31 | }
32 |
33 | public TemplatePath(@NotNull String path, @Nullable String namespace, boolean customPath) {
34 | this(path, customPath);
35 | this.namespace = namespace;
36 | }
37 |
38 | @Attribute("path")
39 | public String getPath() {
40 | return path;
41 | }
42 |
43 | @Nullable
44 | @Attribute("namespace")
45 | public String getNamespace() {
46 | return namespace;
47 | }
48 |
49 | @Override
50 | public TemplatePath clone() {
51 |
52 | try {
53 | super.clone();
54 | } catch (CloneNotSupportedException ignored) {
55 | }
56 |
57 | return new TemplatePath(this.getPath(), this.getNamespace(), this.isCustomPath());
58 | }
59 |
60 | public boolean isCustomPath() {
61 | return customPath;
62 | }
63 |
64 | @Nullable
65 | public VirtualFile getRelativePath(Project project) {
66 | return VfsUtil.findRelativeFile(project.getBaseDir(), this.getPath().split("/"));
67 | }
68 |
69 | public VirtualFile getDirectory() {
70 |
71 | File file = new File(this.getPath());
72 |
73 | if(!file.exists()) {
74 | return null;
75 | }
76 |
77 | return VfsUtil.findFileByIoFile(file, true);
78 | }
79 |
80 | public void setPath(String path) {
81 | this.path = path;
82 | }
83 |
84 | public void setNamespace(@Nullable String namespace) {
85 | this.namespace = namespace;
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/tplugin.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | //数据库字段提示方法(方法名.参数位置), 参数可不设置, 默认为第一个参数, test("字段提示")
4 | "dbMethod": [
5 | "test",
6 | //示例
7 | "save.2"
8 | ],
9 | //数据库字段提示方法, 数据参数, test(["字段提示"=>100])
10 | "dbArrMethod": [
11 | "test"
12 | ],
13 | //数据库提示字段, res["数据库字段"]=100
14 | "dbVar": [
15 | "res",
16 | "map",
17 | "where",
18 | "data",
19 | "this->data"
20 | ],
21 |
22 | //日志开关,不设置默认关闭,该设置重启软件生效
23 | "logEnable": false,
24 | //通过前缀筛选日志,//最好从日志文件中复制前缀,如[ sql ] [ SQL ]
25 | "logPrefix": [
26 | "[ info ] [ PARAM ]"
27 | ],
28 | //通过正则筛选日志
29 | "logRegex":[
30 | "^.*\\[\\sSQL ((?!COLUMNS).)*$" //显示带有[ sql但没是COLUMNS的记录
31 | ]
32 | }
--------------------------------------------------------------------------------