diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/QuteJavaConstants.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/QuteJavaConstants.java
index 93c3c1e6f..942982870 100644
--- a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/QuteJavaConstants.java
+++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/QuteJavaConstants.java
@@ -49,6 +49,7 @@ public class QuteJavaConstants {
public static final String OLD_CHECKED_TEMPLATE_ANNOTATION = "io.quarkus.qute.api.CheckedTemplate";
public static final String CHECKED_TEMPLATE_ANNOTATION_IGNORE_FRAGMENTS = "ignoreFragments";
+ public static final String CHECKED_TEMPLATE_ANNOTATION_BASE_PATH = "basePath";
// @TemplateExtension
diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/AbstractQuteTemplateLinkCollector.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/AbstractQuteTemplateLinkCollector.java
index 0e612fbbe..43254ba20 100644
--- a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/AbstractQuteTemplateLinkCollector.java
+++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/AbstractQuteTemplateLinkCollector.java
@@ -41,6 +41,8 @@
import static com.redhat.devtools.intellij.qute.psi.internal.QuteJavaConstants.OLD_CHECKED_TEMPLATE_ANNOTATION;
import static com.redhat.devtools.intellij.qute.psi.internal.QuteJavaConstants.CHECKED_TEMPLATE_ANNOTATION_IGNORE_FRAGMENTS;
import static com.redhat.devtools.intellij.qute.psi.internal.QuteJavaConstants.TEMPLATE_CLASS;
+import static com.redhat.devtools.intellij.qute.psi.internal.template.datamodel.CheckedTemplateSupport.getBasePath;
+import static com.redhat.devtools.intellij.qute.psi.internal.template.datamodel.CheckedTemplateSupport.isIgnoreFragments;
/**
* Abstract class which collects {@link PsiMethod} or
@@ -108,7 +110,7 @@ public void visitField(PsiField node) {
.getLocationExpressionFromConstructorParameter(node.getName());
}
String fieldName = node.getName();
- collectTemplateLink(node, locationExpression, getTypeDeclaration(node), null, fieldName, false);
+ collectTemplateLink(null, node, locationExpression, getTypeDeclaration(node), null, fieldName, false);
}
super.visitField(node);
}
@@ -137,8 +139,9 @@ public void visitClass(PsiClass node) {
// public static class Templates {
// public static native TemplateInstance book(Book book);
boolean ignoreFragments = isIgnoreFragments(annotation);
+ String basePath = getBasePath(annotation);
for(PsiMethod method : node.getMethods()) {
- collectTemplateLink(method, node, ignoreFragments );
+ collectTemplateLink(basePath, method, node, ignoreFragments );
}
}
}
@@ -146,58 +149,29 @@ public void visitClass(PsiClass node) {
levelTypeDecl--;
}
- /**
- * Returns true if @CheckedTemplate annotation declares that fragment must be
- * ignored and false otherwise.
- *
- *
- * @CheckedTemplate(ignoreFragments=true)
- *
- *
- * @param checkedTemplateAnnotation the CheckedTemplate annotation.
- *
- * @return true if @CheckedTemplate annotation declares that fragment must be
- * ignored and false otherwise.
- */
- private static boolean isIgnoreFragments(PsiAnnotation checkedTemplateAnnotation) {
- Boolean ignoreFragment = null;
- try {
- for(PsiNameValuePair pair : checkedTemplateAnnotation.getParameterList().getAttributes()) {
- if (CHECKED_TEMPLATE_ANNOTATION_IGNORE_FRAGMENTS.equalsIgnoreCase(pair.getAttributeName())) {
- ignoreFragment = AnnotationUtils.getValueAsBoolean(pair);
- }
- }
- } catch (IndexNotReadyException | ProcessCanceledException | CancellationException e) {
- throw e;
- } catch (Exception e) {
- // Do nothing
- }
- return ignoreFragment != null ? ignoreFragment.booleanValue() : false;
- }
-
private static PsiClass getTypeDeclaration(PsiElement node) {
return PsiTreeUtil.getParentOfType(node, PsiClass.class);
}
- private void collectTemplateLink(PsiMethod methodDeclaration, PsiClass type, boolean ignoreFragments) {
+ private void collectTemplateLink(String basePath, PsiMethod methodDeclaration, PsiClass type, boolean ignoreFragments) {
String className = null;
boolean innerClass = levelTypeDecl > 1;
if (innerClass) {
className = PsiTypeUtils.getSimpleClassName(typeRoot.getName());
}
String methodName = methodDeclaration.getName();
- collectTemplateLink(methodDeclaration, null, type, className, methodName, ignoreFragments );
+ collectTemplateLink(basePath, methodDeclaration, null, type, className, methodName, ignoreFragments );
}
- private void collectTemplateLink(PsiElement fieldOrMethod, PsiLiteralValue locationAnnotation, PsiClass type, String className,
+ private void collectTemplateLink(String basePath, PsiElement fieldOrMethod, PsiLiteralValue locationAnnotation, PsiClass type, String className,
String fieldOrMethodName, boolean ignoreFragment ) {
try {
String location = locationAnnotation != null && locationAnnotation.getValue() instanceof String ? (String) locationAnnotation.getValue() : null;
Module project = utils.getModule();
TemplatePathInfo templatePathInfo = location != null
- ? PsiQuteProjectUtils.getTemplatePath(null, location, ignoreFragment)
- : PsiQuteProjectUtils.getTemplatePath(className, fieldOrMethodName, ignoreFragment);
+ ? PsiQuteProjectUtils.getTemplatePath(basePath, null, location, ignoreFragment)
+ : PsiQuteProjectUtils.getTemplatePath(basePath, className, fieldOrMethodName, ignoreFragment);
VirtualFile templateFile = null;
if (location == null) {
diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/template/datamodel/CheckedTemplateSupport.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/template/datamodel/CheckedTemplateSupport.java
index 091bb7f62..f8cd5097e 100644
--- a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/template/datamodel/CheckedTemplateSupport.java
+++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/template/datamodel/CheckedTemplateSupport.java
@@ -80,7 +80,8 @@ protected void processAnnotation(PsiElement javaElement, PsiAnnotation checkedTe
if (javaElement instanceof PsiClass) {
PsiClass type = (PsiClass) javaElement;
boolean ignoreFragments = isIgnoreFragments(checkedTemplateAnnotation);
- collectDataModelTemplateForCheckedTemplate(type, ignoreFragments, context.getTypeResolver(type),
+ String basePath = getBasePath(checkedTemplateAnnotation);
+ collectDataModelTemplateForCheckedTemplate(type, basePath, ignoreFragments, context.getTypeResolver(type),
context.getDataModelProject().getTemplates(), monitor);
}
}
@@ -96,7 +97,7 @@ protected void processAnnotation(PsiElement javaElement, PsiAnnotation checkedTe
* ignored and false otherwise.
* @CheckedTemplate(ignoreFragments=true)
*/
- private static boolean isIgnoreFragments(PsiAnnotation checkedTemplateAnnotation) {
+ public static boolean isIgnoreFragments(PsiAnnotation checkedTemplateAnnotation) {
Boolean ignoreFragment = null;
try {
for (PsiNameValuePair pair : checkedTemplateAnnotation.getParameterList().getAttributes()) {
@@ -112,15 +113,32 @@ private static boolean isIgnoreFragments(PsiAnnotation checkedTemplateAnnotation
return ignoreFragment != null ? ignoreFragment.booleanValue() : false;
}
+ public static String getBasePath(PsiAnnotation checkedTemplateAnnotation) {
+ String basePath = "";
+ try {
+ for (PsiNameValuePair pair : checkedTemplateAnnotation.getParameterList().getAttributes()) {
+ if (CHECKED_TEMPLATE_ANNOTATION_BASE_PATH.equalsIgnoreCase(pair.getAttributeName())) {
+ basePath = pair.getLiteralValue();
+ }
+ }
+ } catch (IndexNotReadyException | ProcessCanceledException | CancellationException e) {
+ throw e;
+ } catch (Exception e) {
+ // Do nothing
+ }
+ return basePath;
+ }
+
/**
* Collect data model template from @CheckedTemplate.
*
* @param type the Java type.
+ * @param basePath the base path relative to the templates root
* @param ignoreFragments true if fragments must be ignored and false otherwise.
* @param templates the data model templates to update with collect of template.
* @param monitor the progress monitor.
*/
- private static void collectDataModelTemplateForCheckedTemplate(PsiClass type, boolean ignoreFragments, ITypeResolver typeResolver,
+ private static void collectDataModelTemplateForCheckedTemplate(PsiClass type, String basePath, boolean ignoreFragments, ITypeResolver typeResolver,
List> templates, ProgressIndicator monitor) {
boolean innerClass = type.getContainingClass() != null;
String className = !innerClass ? null
@@ -131,7 +149,7 @@ private static void collectDataModelTemplateForCheckedTemplate(PsiClass type, bo
PsiMethod[] methods = type.getMethods();
for (PsiMethod method : methods) {
// src/main/resources/templates/${className}/${methodName}.qute.html
- TemplatePathInfo templatePathInfo = getTemplatePath(className, method.getName(), ignoreFragments);
+ TemplatePathInfo templatePathInfo = getTemplatePath(basePath, className, method.getName(), ignoreFragments);
// Get or create template
String templateUri = templatePathInfo.getTemplateUri();
diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/template/datamodel/TemplateFieldSupport.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/template/datamodel/TemplateFieldSupport.java
index a07d6b5c2..b9834887f 100644
--- a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/template/datamodel/TemplateFieldSupport.java
+++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/template/datamodel/TemplateFieldSupport.java
@@ -117,7 +117,7 @@ private static DataModelTemplate createTemplateDataModel(Psi
String location = locationFromConstructorParameter != null ? locationFromConstructorParameter : getLocation(field);
String fieldName = field.getName();
// src/main/resources/templates/${methodName}.qute.html
- String templateUri = getTemplatePath(null, location != null ? location : fieldName, true).getTemplateUri();
+ String templateUri = getTemplatePath(null,null, location != null ? location : fieldName, true).getTemplateUri();
// Create template data model with:
// - template uri : Qute template file which must be bind with data model.
diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/utils/PsiQuteProjectUtils.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/utils/PsiQuteProjectUtils.java
index 1876ab861..8d24bb3ef 100644
--- a/src/main/java/com/redhat/devtools/intellij/qute/psi/utils/PsiQuteProjectUtils.java
+++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/utils/PsiQuteProjectUtils.java
@@ -61,8 +61,14 @@ public static boolean hasQuteSupport(Module javaProject) {
return PsiTypeUtils.findType(javaProject, QuteJavaConstants.ENGINE_BUILDER_CLASS) != null;
}
- public static String getTemplatePath(String className, String methodOrFieldName) {
+ public static String getTemplatePath(String basePath, String className, String methodOrFieldName) {
StringBuilder path = new StringBuilder(TEMPLATES_BASE_DIR);
+ if (basePath != null && !basePath.isBlank()){
+ path.append(basePath.startsWith("/")? basePath.substring(1): basePath);
+ if (!basePath.endsWith("/")) {
+ path.append('/');
+ }
+ }
if (className != null) {
path.append(className);
path.append('/');
@@ -70,9 +76,15 @@ public static String getTemplatePath(String className, String methodOrFieldName)
return path.append(methodOrFieldName).toString();
}
- public static TemplatePathInfo getTemplatePath(String className, String methodOrFieldName, boolean ignoreFragments) {
+ public static TemplatePathInfo getTemplatePath(String basePath, String className, String methodOrFieldName, boolean ignoreFragments) {
String fragmentId = null;
StringBuilder templateUri = new StringBuilder(TEMPLATES_BASE_DIR);
+ if (basePath != null && !basePath.isBlank()){
+ templateUri.append(basePath.startsWith("/")? basePath.substring(1): basePath);
+ if (!basePath.endsWith("/")) {
+ templateUri.append('/');
+ }
+ }
if (className != null) {
templateUri.append(className);
templateUri.append('/');