feat(config): persistent context, path portability, and refined browsing
- Generator now remembers last used directory for Action Beans and Datasets independently per project. - Added settings to customize automatic file opening and table limits. - Enforced project-relative paths for i18n/XSD for better project portability. - Refined File Browser to start at current directory with strict project scope. - Implemented DynFormAnnotator for structural validation. - Bumped plugin version to 3.2.7.
This commit is contained in:
@@ -2,6 +2,8 @@ package com.sdk.dynform.tools.dynform;
|
||||
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.patterns.PlatformPatterns;
|
||||
import com.intellij.patterns.XmlPatterns;
|
||||
import com.intellij.psi.*;
|
||||
@@ -229,6 +231,20 @@ public class DynFormCompletionContributor extends CompletionContributor {
|
||||
addFormFieldsForNameRecursive(parameters.getOriginalFile(), resultSet, new HashSet<>());
|
||||
}
|
||||
});
|
||||
|
||||
// XML completion for INCLUDE:FILE
|
||||
extend(CompletionType.BASIC, XmlPatterns.psiElement()
|
||||
.inside(XmlPatterns.xmlAttributeValue()
|
||||
.withParent(XmlPatterns.xmlAttribute().withName("FILE")
|
||||
.withParent(XmlPatterns.xmlTag().withName("INCLUDE")))),
|
||||
new CompletionProvider<CompletionParameters>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||
@NotNull ProcessingContext context,
|
||||
@NotNull CompletionResultSet resultSet) {
|
||||
addFileIncludeCompletions(parameters, resultSet);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addFieldsInTagRecursive(XmlTag container, @NotNull CompletionResultSet resultSet) {
|
||||
@@ -254,7 +270,7 @@ public class DynFormCompletionContributor extends CompletionContributor {
|
||||
|
||||
private void addDatasetsInFileRecursive(PsiFile file, @NotNull CompletionResultSet resultSet, Set<PsiFile> visited) {
|
||||
if (file == null || !visited.add(file)) return;
|
||||
|
||||
|
||||
// 1. Add datasets from current file
|
||||
addDatasetsInFile(file, resultSet);
|
||||
|
||||
@@ -391,7 +407,7 @@ public class DynFormCompletionContributor extends CompletionContributor {
|
||||
private PsiElement findDatasetInFileRecursiveForCompletion(PsiFile file, String id, Set<PsiFile> visited) {
|
||||
if (file == null || !visited.add(file)) return null;
|
||||
if (!(file instanceof XmlFile xmlFile)) return null;
|
||||
|
||||
|
||||
XmlTag rootTag = xmlFile.getRootTag();
|
||||
if (rootTag == null) return null;
|
||||
|
||||
@@ -455,6 +471,78 @@ public class DynFormCompletionContributor extends CompletionContributor {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addFileIncludeCompletions(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet resultSet) {
|
||||
String value = parameters.getPosition().getText().replace(CompletionUtil.DUMMY_IDENTIFIER_TRIMMED, "");
|
||||
PsiFile contextFile = parameters.getOriginalFile();
|
||||
Project project = contextFile.getProject();
|
||||
|
||||
if (value.startsWith("#")) {
|
||||
// Suggest files in the current module's view/frm
|
||||
VirtualFile moduleDir = DynFormPathUtils.findModuleDir(contextFile);
|
||||
if (moduleDir != null) {
|
||||
VirtualFile frmDir = moduleDir.findFileByRelativePath("view/frm");
|
||||
if (frmDir != null) {
|
||||
addFrmlFilesRecursive(frmDir, "#", "", resultSet);
|
||||
}
|
||||
}
|
||||
} else if (value.startsWith("/")) {
|
||||
// Suggest modules or files in modules
|
||||
String path = value.substring(1);
|
||||
int firstSlash = path.indexOf("/");
|
||||
if (firstSlash < 0) {
|
||||
// Suggest modules
|
||||
List<String> modules = DynFormPathUtils.getAllModules(project);
|
||||
for (String module : modules) {
|
||||
resultSet.addElement(LookupElementBuilder.create("/" + module + "/")
|
||||
.withIcon(com.intellij.icons.AllIcons.Nodes.Module)
|
||||
.withPresentableText("/" + module));
|
||||
}
|
||||
} else {
|
||||
// Suggest files in the selected module
|
||||
String moduleName = path.substring(0, firstSlash);
|
||||
VirtualFile moduleBase = DynFormPathUtils.getModuleBaseDir(project);
|
||||
if (moduleBase != null) {
|
||||
VirtualFile frmDir = moduleBase.findFileByRelativePath(moduleName + "/view/frm");
|
||||
if (frmDir != null) {
|
||||
addFrmlFilesRecursive(frmDir, "/" + moduleName + "/", "", resultSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Suggest relative files (basic implementation: current directory)
|
||||
VirtualFile currentDir = contextFile.getVirtualFile().getParent();
|
||||
if (currentDir != null) {
|
||||
for (VirtualFile child : currentDir.getChildren()) {
|
||||
if (child.isDirectory()) {
|
||||
resultSet.addElement(LookupElementBuilder.create(child.getName() + "/")
|
||||
.withIcon(com.intellij.icons.AllIcons.Nodes.Folder));
|
||||
} else if (child.getName().endsWith(".frml")) {
|
||||
resultSet.addElement(LookupElementBuilder.create(child.getName())
|
||||
.withIcon(com.intellij.icons.AllIcons.FileTypes.Xml));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Also suggest starting with # or /
|
||||
resultSet.addElement(LookupElementBuilder.create("#")
|
||||
.withTailText(" (Current Module)"));
|
||||
resultSet.addElement(LookupElementBuilder.create("/")
|
||||
.withTailText(" (Cross Module)"));
|
||||
}
|
||||
}
|
||||
|
||||
private void addFrmlFilesRecursive(VirtualFile dir, String prefix, String subPath, @NotNull CompletionResultSet resultSet) {
|
||||
for (VirtualFile child : dir.getChildren()) {
|
||||
String currentSubPath = subPath.isEmpty() ? child.getName() : subPath + "/" + child.getName();
|
||||
if (child.isDirectory()) {
|
||||
addFrmlFilesRecursive(child, prefix, currentSubPath, resultSet);
|
||||
} else if (child.getName().endsWith(".frml")) {
|
||||
resultSet.addElement(LookupElementBuilder.create(prefix + currentSubPath)
|
||||
.withIcon(com.intellij.icons.AllIcons.FileTypes.Xml)
|
||||
.withPresentableText(currentSubPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addFormFieldsForNameRecursive(PsiFile file, @NotNull CompletionResultSet resultSet, Set<PsiFile> visited) {
|
||||
if (file == null || !visited.add(file)) return;
|
||||
if (!(file instanceof XmlFile xmlFile)) return;
|
||||
|
||||
Reference in New Issue
Block a user