feat(dynform): structural validation and generator enhancements
- Implemented DynFormAnnotator to validate field usage in <LAYOUT> and <FILTERS> against their respective <FIELDS> definitions. - Refined ActionBean generator logic for NUMBER and DATE column width calculation. - Improved window management and focus for newly generated files using FileEditorManagerEx. - Bumped plugin version to 3.2.6.
This commit is contained in:
@@ -4,7 +4,7 @@ plugins {
|
|||||||
id("org.jetbrains.intellij.platform") version "2.7.0"
|
id("org.jetbrains.intellij.platform") version "2.7.0"
|
||||||
}
|
}
|
||||||
group = "com.sdk.dynform.tools"
|
group = "com.sdk.dynform.tools"
|
||||||
version = "3.2.5"
|
version = "3.2.6"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -38,19 +38,18 @@ intellijPlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
changeNotes = """
|
changeNotes = """
|
||||||
|
<h2>[3.2.6]</h2>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Structural Validation:</strong> Introduced a new Annotator to validate that all fields used in <code><LAYOUT></code> and <code><FILTERS></code> are correctly defined in their respective <code><FIELDS></code> sections.</li>
|
||||||
|
<li><strong>Generator Logic Update:</strong> Refined the column width calculation for NUMBER and DATE types in the ActionBean generator for better XML compatibility.</li>
|
||||||
|
<li><strong>Improved File Opening:</strong> Switched to <code>FileEditorManagerEx</code> for opening generated files, ensuring better window focus and management in recent IDE versions.</li>
|
||||||
|
</ul>
|
||||||
<h2>[3.2.5]</h2>
|
<h2>[3.2.5]</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Dataset to Form Mapping:</strong> Implemented comprehensive reference and completion support for the <code>FORM-NAME</code> attribute in <code>DATASET > FIELDS > FIELD</code>.</li>
|
<li><strong>Dataset to Form Mapping:</strong> Implemented comprehensive reference and completion support for the <code>FORM-NAME</code> attribute in <code>DATASET > FIELDS > FIELD</code>.</li>
|
||||||
<li><strong>Smart Field Resolution:</strong> <code>FORM-NAME</code> now correctly resolves to hidden fields in <code>FORM_ENTRY > FIELDS</code> and any named fields within <code>FORM_ENTRY > LAYOUT</code>.</li>
|
<li><strong>Smart Field Resolution:</strong> <code>FORM-NAME</code> now correctly resolves to hidden fields in <code>FORM_ENTRY > FIELDS</code> and any named fields within <code>FORM_ENTRY > LAYOUT</code>.</li>
|
||||||
<li><strong>Recursive Form Scanning:</strong> Enhanced field discovery to scan across all form entries in the current and recursively included <code>.frml</code> files.</li>
|
<li><strong>Recursive Form Scanning:</strong> Enhanced field discovery to scan across all form entries in the current and recursively included <code>.frml</code> files.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>[3.2.4]</h2>
|
|
||||||
<ul>
|
|
||||||
<li><strong>Persistent Generation Directories:</strong> Generator now remembers the last used directory for Action Beans and Dataset XMLs independently per project.</li>
|
|
||||||
<li><strong>Auto-Open Generated Files:</strong> Added configuration to automatically open newly created files in the editor, with a customizable limit on the number of files.</li>
|
|
||||||
<li><strong>Strict Project-Relative Paths:</strong> I18n and XSD configuration now strictly enforces file selection within the project root and stores paths as relative for maximum portability.</li>
|
|
||||||
<li><strong>Smart File Browser:</strong> Improved file picker logic to automatically start at the current configured directory if it's within the project, falling back to the project root otherwise.</li>
|
|
||||||
</ul>
|
|
||||||
<h2>[3.2.3]</h2>
|
<h2>[3.2.3]</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Advanced Data Referencing:</strong> Implemented comprehensive reference and completion support for <code><FOREIGN-DATASETS></code> and <code><MASTER-DATA></code> structures.</li>
|
<li><strong>Advanced Data Referencing:</strong> Implemented comprehensive reference and completion support for <code><FOREIGN-DATASETS></code> and <code><MASTER-DATA></code> structures.</li>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import com.intellij.database.model.DasTableKey;
|
|||||||
import com.intellij.database.psi.DbTable;
|
import com.intellij.database.psi.DbTable;
|
||||||
import com.intellij.database.util.DasUtil;
|
import com.intellij.database.util.DasUtil;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
|
||||||
import com.intellij.openapi.progress.ProgressIndicator;
|
import com.intellij.openapi.progress.ProgressIndicator;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
@@ -62,7 +62,9 @@ public class GeneratorServices {
|
|||||||
private void openInEditor(VirtualFile file) {
|
private void openInEditor(VirtualFile file) {
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
ApplicationManager.getApplication().invokeLater(() -> {
|
ApplicationManager.getApplication().invokeLater(() -> {
|
||||||
FileEditorManager.getInstance(project).openFile(file, true);
|
FileEditorManagerEx manager = FileEditorManagerEx.getInstanceEx(project);
|
||||||
|
// Using 3-parameter openFile from FileEditorManagerEx to ensure it's handled correctly
|
||||||
|
manager.openFile(file, true, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,16 +226,19 @@ public class GeneratorServices {
|
|||||||
colModel.put("isPk", primaryKeys.contains(colName));
|
colModel.put("isPk", primaryKeys.contains(colName));
|
||||||
colModel.put("customType", dataType);
|
colModel.put("customType", dataType);
|
||||||
|
|
||||||
|
int width = column.getDasType().toDataType().getLength();
|
||||||
|
|
||||||
// XML Specific fields
|
// XML Specific fields
|
||||||
String xmlType = "TEXT";
|
String xmlType = "TEXT";
|
||||||
if ("NUMBER".equals(dataType)) {
|
if ("NUMBER".equals(dataType)) {
|
||||||
xmlType = "NUMBER";
|
xmlType = "NUMBER";
|
||||||
|
width = String.valueOf(width).length();
|
||||||
} else if ("DATE".equals(dataType)) {
|
} else if ("DATE".equals(dataType)) {
|
||||||
xmlType = "DATE";
|
xmlType = "DATE";
|
||||||
|
width = "dd/mm/yyyy hh:mm:ss".length();
|
||||||
}
|
}
|
||||||
colModel.put("xmlType", xmlType);
|
|
||||||
|
|
||||||
int width = column.getDasType().toDataType().getLength();
|
colModel.put("xmlType", xmlType);
|
||||||
colModel.put("width", Math.max(width, 0));
|
colModel.put("width", Math.max(width, 0));
|
||||||
|
|
||||||
// Label generation: Use field comment if available, otherwise fallback to generated key
|
// Label generation: Use field comment if available, otherwise fallback to generated key
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package com.sdk.dynform.tools.dynform;
|
||||||
|
|
||||||
|
import com.intellij.lang.annotation.AnnotationHolder;
|
||||||
|
import com.intellij.lang.annotation.Annotator;
|
||||||
|
import com.intellij.lang.annotation.HighlightSeverity;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.xml.XmlAttribute;
|
||||||
|
import com.intellij.psi.xml.XmlAttributeValue;
|
||||||
|
import com.intellij.psi.xml.XmlTag;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class DynFormAnnotator implements Annotator {
|
||||||
|
@Override
|
||||||
|
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
||||||
|
if (!(element instanceof XmlAttributeValue attrValue)) return;
|
||||||
|
|
||||||
|
PsiElement parent = attrValue.getParent();
|
||||||
|
if (!(parent instanceof XmlAttribute attr)) return;
|
||||||
|
|
||||||
|
if (!"NAME".equals(attr.getName())) return;
|
||||||
|
|
||||||
|
PsiElement tagElem = attr.getParent();
|
||||||
|
if (!(tagElem instanceof XmlTag tag) || !"FIELD".equals(tag.getName())) return;
|
||||||
|
|
||||||
|
// Check if this FIELD is inside a LAYOUT tag
|
||||||
|
XmlTag layoutTag = tag.getParentTag();
|
||||||
|
while (layoutTag != null && !"LAYOUT".equals(layoutTag.getName())) {
|
||||||
|
layoutTag = layoutTag.getParentTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layoutTag == null) return;
|
||||||
|
|
||||||
|
// The "Owner" of the LAYOUT (e.g., FORM_ENTRY, FILTERS, GRID-EDITOR)
|
||||||
|
XmlTag ownerTag = layoutTag.getParentTag();
|
||||||
|
if (ownerTag == null) return;
|
||||||
|
|
||||||
|
String fieldName = attrValue.getValue();
|
||||||
|
if (fieldName == null || fieldName.isEmpty()) return;
|
||||||
|
|
||||||
|
// Look for the FIELDS tag that is a sibling of the current LAYOUT
|
||||||
|
XmlTag fieldsTag = ownerTag.findFirstSubTag("FIELDS");
|
||||||
|
if (fieldsTag == null) {
|
||||||
|
holder.newAnnotation(HighlightSeverity.ERROR, "No <FIELDS> definition found in <" + ownerTag.getName() + ">")
|
||||||
|
.range(attrValue.getTextRange())
|
||||||
|
.create();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isFieldDefined(fieldsTag, fieldName)) {
|
||||||
|
holder.newAnnotation(HighlightSeverity.ERROR, "Field '" + fieldName + "' is not defined in <FIELDS> of <" + ownerTag.getName() + ">")
|
||||||
|
.range(attrValue.getTextRange())
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isFieldDefined(XmlTag fieldsTag, String name) {
|
||||||
|
for (XmlTag field : fieldsTag.findSubTags("FIELD")) {
|
||||||
|
if (name.equals(field.getAttributeValue("NAME"))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Also check inside SECTIONS or ROWS if any
|
||||||
|
for (XmlTag sub : fieldsTag.getSubTags()) {
|
||||||
|
if ("SECTION".equals(sub.getName()) || "ROW".equals(sub.getName())) {
|
||||||
|
if (isFieldDefined(sub, name)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasAncestorWithName(XmlTag tag, String name) {
|
||||||
|
XmlTag current = tag.getParentTag();
|
||||||
|
while (current != null) {
|
||||||
|
if (name.equals(current.getName())) return true;
|
||||||
|
current = current.getParentTag();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,12 @@
|
|||||||
]]></description>
|
]]></description>
|
||||||
|
|
||||||
<change-notes><![CDATA[
|
<change-notes><![CDATA[
|
||||||
|
<h2>[3.2.6]</h2>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Structural Validation:</strong> Introduced a new Annotator to validate that all fields used in <code><LAYOUT></code> and <code><FILTERS></code> are correctly defined in their respective <code><FIELDS></code> sections.</li>
|
||||||
|
<li><strong>Generator Logic Update:</strong> Refined the column width calculation for NUMBER and DATE types in the ActionBean generator for better XML compatibility.</li>
|
||||||
|
<li><strong>Improved File Opening:</strong> Switched to <code>FileEditorManagerEx</code> for opening generated files, ensuring better window focus and management in recent IDE versions.</li>
|
||||||
|
</ul>
|
||||||
<h2>[3.2.5]</h2>
|
<h2>[3.2.5]</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Dataset to Form Mapping:</strong> Implemented comprehensive reference and completion support for the <code>FORM-NAME</code> attribute in <code>DATASET > FIELDS > FIELD</code>.</li>
|
<li><strong>Dataset to Form Mapping:</strong> Implemented comprehensive reference and completion support for the <code>FORM-NAME</code> attribute in <code>DATASET > FIELDS > FIELD</code>.</li>
|
||||||
@@ -188,5 +194,6 @@
|
|||||||
<completion.contributor language="XML" implementationClass="com.sdk.dynform.tools.dynform.DynFormCompletionContributor"/>
|
<completion.contributor language="XML" implementationClass="com.sdk.dynform.tools.dynform.DynFormCompletionContributor"/>
|
||||||
<completion.contributor language="JavaScript" implementationClass="com.sdk.dynform.tools.dynform.DynFormCompletionContributor"/>
|
<completion.contributor language="JavaScript" implementationClass="com.sdk.dynform.tools.dynform.DynFormCompletionContributor"/>
|
||||||
|
|
||||||
|
<annotator language="XML" implementationClass="com.sdk.dynform.tools.dynform.DynFormAnnotator"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
|
|||||||
Reference in New Issue
Block a user