From fbd745217314df56e9776074a1764116b6095785 Mon Sep 17 00:00:00 2001 From: Fred Bricon Date: Mon, 18 Sep 2023 12:10:09 +0200 Subject: [PATCH] fix: respect basePath in @CheckedTemplate to find templates Signed-off-by: Fred Bricon --- .../qute/ItemResourceWithCustomBasePath.java | 39 +++++++++++ .../qute/ItemTemplatesCustomBasePath.java | 15 ++++ .../qute/psi/internal/QuteJavaConstants.java | 1 + .../AbstractQuteTemplateLinkCollector.java | 50 ++++---------- .../java/QuteJavaCodeLensCollector.java | 2 +- .../java/QuteJavaDiagnosticsCollector.java | 18 +++-- .../java/QuteJavaDocumentLinkCollector.java | 2 +- .../datamodel/CheckedTemplateSupport.java | 26 +++++-- .../datamodel/TemplateFieldSupport.java | 2 +- .../qute/psi/utils/PsiQuteProjectUtils.java | 36 +++++++--- .../qute/psi/java/JavaCodeLensTest.java | 69 +++++++++++++++++++ .../qute/psi/java/JavaDiagnosticsTest.java | 55 +++++++++++++++ .../qute/psi/java/JavaDocumentLinkTest.java | 30 ++++++++ 13 files changed, 286 insertions(+), 59 deletions(-) create mode 100644 projects/qute/projects/maven/qute-quickstart/src/main/java/org/acme/qute/ItemResourceWithCustomBasePath.java create mode 100644 projects/qute/projects/maven/qute-quickstart/src/main/java/org/acme/qute/ItemTemplatesCustomBasePath.java diff --git a/projects/qute/projects/maven/qute-quickstart/src/main/java/org/acme/qute/ItemResourceWithCustomBasePath.java b/projects/qute/projects/maven/qute-quickstart/src/main/java/org/acme/qute/ItemResourceWithCustomBasePath.java new file mode 100644 index 000000000..56d1cafad --- /dev/null +++ b/projects/qute/projects/maven/qute-quickstart/src/main/java/org/acme/qute/ItemResourceWithCustomBasePath.java @@ -0,0 +1,39 @@ +package org.acme.qute; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import io.quarkus.qute.CheckedTemplate; +import io.quarkus.qute.TemplateExtension; +import io.quarkus.qute.TemplateInstance; + +@Path("items3") +public class ItemResourceWithCustomBasePath { + + @CheckedTemplate(basePath="ItemResourceWithFragment") + static class Templates { + static native TemplateInstance items(List items); + static native TemplateInstance items$id1(List items); + static native TemplateInstance items3$id2(List items); + static native TemplateInstance items3$(List items); + } + + @GET + @Produces(MediaType.TEXT_HTML) + public TemplateInstance get() { + List items = new ArrayList<>(); + items.add(new Item(new BigDecimal(10), "Apple")); + items.add(new Item(new BigDecimal(16), "Pear")); + items.add(new Item(new BigDecimal(30), "Orange")); + return Templates.items(items); + } + + +} \ No newline at end of file diff --git a/projects/qute/projects/maven/qute-quickstart/src/main/java/org/acme/qute/ItemTemplatesCustomBasePath.java b/projects/qute/projects/maven/qute-quickstart/src/main/java/org/acme/qute/ItemTemplatesCustomBasePath.java new file mode 100644 index 000000000..8cfebe581 --- /dev/null +++ b/projects/qute/projects/maven/qute-quickstart/src/main/java/org/acme/qute/ItemTemplatesCustomBasePath.java @@ -0,0 +1,15 @@ +package org.acme.qute; + +import java.util.List; +import io.quarkus.qute.CheckedTemplate; +import io.quarkus.qute.TemplateInstance; + +@CheckedTemplate(basePath="ItemResourceWithFragment") +public class ItemTemplatesCustomBasePath { + + static native TemplateInstance items(List items); + static native TemplateInstance items$id1(List items); + static native TemplateInstance items3$id2(List items); + static native TemplateInstance items3$(List items); + +} \ No newline at end of file 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..6cad3ba03 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) { @@ -208,7 +182,7 @@ private void collectTemplateLink(PsiElement fieldOrMethod, PsiLiteralValue locat } else { templateFile = getVirtualFile(project, templatePathInfo.getTemplateUri(), ""); } - collectTemplateLink(fieldOrMethod, locationAnnotation, type, className, fieldOrMethodName, location, + collectTemplateLink(basePath, fieldOrMethod, locationAnnotation, type, className, fieldOrMethodName, location, templateFile, templatePathInfo); } catch (IndexNotReadyException | ProcessCanceledException | CancellationException e) { throw e; @@ -275,7 +249,7 @@ protected Range createRange(PsiElement fieldOrMethod) { return utils.toRange(typeRoot, tr.getStartOffset(), tr.getLength()); } - protected abstract void collectTemplateLink(PsiElement node, PsiLiteralValue locationAnnotation, PsiClass type, + protected abstract void collectTemplateLink(String basePath, PsiElement node, PsiLiteralValue locationAnnotation, PsiClass type, String className, String fieldOrMethodName, String location, VirtualFile templateFile, TemplatePathInfo templatePathInfo); private static boolean isTemplateType(PsiType type) { diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/QuteJavaCodeLensCollector.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/QuteJavaCodeLensCollector.java index 170f2299b..6b689ee59 100644 --- a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/QuteJavaCodeLensCollector.java +++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/QuteJavaCodeLensCollector.java @@ -59,7 +59,7 @@ public QuteJavaCodeLensCollector(PsiFile typeRoot, List lenses, IPsiUt } @Override - protected void collectTemplateLink(PsiElement fieldOrMethod, PsiLiteralValue locationAnnotation, PsiClass type, String className, String fieldOrMethodName, + protected void collectTemplateLink(String basePath, PsiElement fieldOrMethod, PsiLiteralValue locationAnnotation, PsiClass type, String className, String fieldOrMethodName, String location, VirtualFile templateFile, TemplatePathInfo templatePathInfo) { if (!templatePathInfo.isValid()) { // It is an empty fragment which is not valid, don't generate a codelens. diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/QuteJavaDiagnosticsCollector.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/QuteJavaDiagnosticsCollector.java index f564c6e52..6e2a9ae6e 100644 --- a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/QuteJavaDiagnosticsCollector.java +++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/QuteJavaDiagnosticsCollector.java @@ -26,6 +26,9 @@ import java.util.List; +import static com.redhat.devtools.intellij.qute.psi.utils.PsiQuteProjectUtils.appendAndSlash; +import static io.quarkus.qute.CheckedTemplate.DEFAULTED; + /** * Report diagnostics error for non existing Qute template for: * @@ -49,13 +52,13 @@ public QuteJavaDiagnosticsCollector(PsiFile typeRoot, List diagnosti } @Override - protected void collectTemplateLink(PsiElement fieldOrMethod, PsiLiteralValue locationAnnotation, PsiClass type, String className, + protected void collectTemplateLink(String basePath, PsiElement fieldOrMethod, PsiLiteralValue locationAnnotation, PsiClass type, String className, String fieldOrMethodName, String location, VirtualFile templateFile, TemplatePathInfo templatePathInfo) { QuteErrorCode error = getQuteErrorCode(templatePathInfo, templateFile); if (error == null) { return; } - String path = createPath(className, fieldOrMethodName, location); + String path = createPath(basePath, className, fieldOrMethodName, location); String fragmentId = templatePathInfo.getFragmentId(); if (templatePathInfo.hasFragment() && path.endsWith(fragmentId)) { // Adjust path by removing fragment information @@ -92,14 +95,17 @@ private static QuteErrorCode getQuteErrorCode(TemplatePathInfo templatePathInfo, return null; } - private static String createPath(String className, String fieldOrMethodName, String location) { + private static String createPath(String basePath, String className, String fieldOrMethodName, String location) { if (location != null) { return location; } - if (className == null) { - return fieldOrMethodName; + StringBuilder path = new StringBuilder(); + if (basePath != null && !DEFAULTED.equals(basePath)) { + appendAndSlash(path, basePath); + } else if (className != null){ + appendAndSlash(path, className); } - return className + '/' + fieldOrMethodName; + return path.append(fieldOrMethodName).toString(); } private static Diagnostic createDiagnostic(Range range, DiagnosticSeverity severity, IQuteErrorCode errorCode, diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/QuteJavaDocumentLinkCollector.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/QuteJavaDocumentLinkCollector.java index bdb66f493..23cfabef5 100644 --- a/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/QuteJavaDocumentLinkCollector.java +++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/internal/java/QuteJavaDocumentLinkCollector.java @@ -50,7 +50,7 @@ public QuteJavaDocumentLinkCollector(PsiFile typeRoot, List links, } @Override - protected void collectTemplateLink(PsiElement fieldOrMethod, PsiLiteralValue locationAnnotation, PsiClass type, String className, + protected void collectTemplateLink(String basePath, PsiElement fieldOrMethod, PsiLiteralValue locationAnnotation, PsiClass type, String className, String fieldOrMethodName, String location, VirtualFile templateFile, TemplatePathInfo templatePathInfo) { if (!templatePathInfo.isValid()) { // It is an empty fragment which is not valid, don't generate a document link. 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..eb952fd1b 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 = null; + 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..27078f817 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 @@ -17,6 +17,7 @@ import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils; import com.redhat.devtools.intellij.qute.psi.internal.QuteJavaConstants; import com.redhat.qute.commons.ProjectInfo; +import org.jetbrains.annotations.NotNull; /** * JDT Qute utilities. @@ -28,6 +29,11 @@ public class PsiQuteProjectUtils { private static final String TEMPLATES_BASE_DIR = "src/main/resources/templates/"; + /** + * Value for Qute annotations indicating behaviour should be using the default + */ + private static final String DEFAULTED = "<>"; + private PsiQuteProjectUtils() { } @@ -61,21 +67,23 @@ 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 (className != null) { - path.append(className); - path.append('/'); + if (basePath != null && !DEFAULTED.equals(basePath)) { + appendAndSlash(path, basePath); + } else if (className != null) { + appendAndSlash(path, className); } 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 (className != null) { - templateUri.append(className); - templateUri.append('/'); + if (basePath != null && !DEFAULTED.equals(basePath)) { + appendAndSlash(templateUri, basePath); + } else if (className != null) { + appendAndSlash(templateUri, className); } if (!ignoreFragments) { int fragmentIndex = methodOrFieldName != null ? methodOrFieldName.lastIndexOf('$') : -1; @@ -87,4 +95,16 @@ public static TemplatePathInfo getTemplatePath(String className, String methodOr templateUri.append(methodOrFieldName); return new TemplatePathInfo(templateUri.toString(), fragmentId); } + + /** + * Appends a segment to a path, add trailing "/" if necessary + * @param path the path to append to + * @param segment the segment to append to the path + */ + public static void appendAndSlash(@NotNull StringBuilder path, @NotNull String segment) { + path.append(segment); + if (!segment.endsWith("/")) { + path.append('/'); + } + } } diff --git a/src/test/java/com/redhat/devtools/intellij/qute/psi/java/JavaCodeLensTest.java b/src/test/java/com/redhat/devtools/intellij/qute/psi/java/JavaCodeLensTest.java index 92a0fa336..6865f842f 100644 --- a/src/test/java/com/redhat/devtools/intellij/qute/psi/java/JavaCodeLensTest.java +++ b/src/test/java/com/redhat/devtools/intellij/qute/psi/java/JavaCodeLensTest.java @@ -236,6 +236,75 @@ public void testCheckedTemplateWithFragment() throws Exception { "qute.command.generate.template.file", Arrays.asList(items2Uri_id2))); } + public void testCheckedTemplateWithCustomBasePath() throws Exception { + + // @CheckedTemplate(basePath="ItemResourceWithFragment") + //public class ItemTemplatesCustomBasePath { + // + // static native TemplateInstance items(List items); + // static native TemplateInstance items$id1(List items); + // static native TemplateInstance items3$id2(List items); + // static native TemplateInstance items3$(List items); + //} + + QuteJavaCodeLensParams params = new QuteJavaCodeLensParams(); + String javaFileUri = LSPIJUtils.toUri(module).resolve("src/main/java/org/acme/qute/ItemTemplatesCustomBasePath.java").toASCIIString(); + params.setUri(javaFileUri); + + List lenses = QuteSupportForJava.getInstance().codeLens(params, PsiUtilsLSImpl.getInstance(myProject), + new EmptyProgressIndicator()); + assertEquals(3, lenses.size()); + + String itemsUri = LSPIJUtils.toUri(module).resolve("/src/main/resources/templates/ItemResourceWithFragment/items.html").toASCIIString(); + String items3Uri = LSPIJUtils.toUri(module).resolve("src/main/resources/templates/ItemResourceWithFragment/items3.html").toASCIIString(); + + assertCodeLens(lenses, // + cl(r(9, 1, 9, 56), // + "Open `src/main/resources/templates/ItemResourceWithFragment/items.html`", // + "qute.command.open.uri", Arrays.asList(itemsUri)), // + cl(r(10, 1, 10, 60), // + "Open `id1` fragment of `src/main/resources/templates/ItemResourceWithFragment/items.html`", // + "qute.command.open.uri", Arrays.asList(itemsUri, "id1")), // + cl(r(11, 1, 11, 61), // + "Create `src/main/resources/templates/ItemResourceWithFragment/items3.html`", // + "qute.command.generate.template.file", Arrays.asList(items3Uri))); + + } + + public void testCheckedTemplateInInnerClassWithCustomBasePath() throws Exception { + + // @CheckedTemplate(basePath="ItemResourceWithFragment") + //public class ItemTemplatesCustomBasePath { + // + // static native TemplateInstance items(List items); + // static native TemplateInstance items$id1(List items); + // static native TemplateInstance items3$id2(List items); + // static native TemplateInstance items3$(List items); + //} + + QuteJavaCodeLensParams params = new QuteJavaCodeLensParams(); + String javaFileUri = LSPIJUtils.toUri(module).resolve("src/main/java/org/acme/qute/ItemTemplatesCustomBasePath.java").toASCIIString(); + params.setUri(javaFileUri); + + List lenses = QuteSupportForJava.getInstance().codeLens(params, PsiUtilsLSImpl.getInstance(myProject), + new EmptyProgressIndicator()); + assertEquals(3, lenses.size()); + + String itemsUri = LSPIJUtils.toUri(module).resolve("/src/main/resources/templates/ItemResourceWithFragment/items.html").toASCIIString(); + String items3Uri = LSPIJUtils.toUri(module).resolve("src/main/resources/templates/ItemResourceWithFragment/items3.html").toASCIIString(); + + assertCodeLens(lenses, // + cl(r(9, 1, 9, 56), // + "Open `src/main/resources/templates/ItemResourceWithFragment/items.html`", // + "qute.command.open.uri", Arrays.asList(itemsUri)), // + cl(r(10, 1, 10, 60), // + "Open `id1` fragment of `src/main/resources/templates/ItemResourceWithFragment/items.html`", // + "qute.command.open.uri", Arrays.asList(itemsUri, "id1")), // + cl(r(11, 1, 11, 61), // + "Create `src/main/resources/templates/ItemResourceWithFragment/items3.html`", // + "qute.command.generate.template.file", Arrays.asList(items3Uri))); + + } @Test public void testCheckedTemplateInInnerClassWithFragment() throws Exception { diff --git a/src/test/java/com/redhat/devtools/intellij/qute/psi/java/JavaDiagnosticsTest.java b/src/test/java/com/redhat/devtools/intellij/qute/psi/java/JavaDiagnosticsTest.java index 50c71ec87..195e304e3 100644 --- a/src/test/java/com/redhat/devtools/intellij/qute/psi/java/JavaDiagnosticsTest.java +++ b/src/test/java/com/redhat/devtools/intellij/qute/psi/java/JavaDiagnosticsTest.java @@ -224,6 +224,61 @@ public void testCheckedTemplateInInnerClassWithFragment() throws Exception { DiagnosticSeverity.Error, "qute", QuteErrorCode.NoMatchingTemplate.name())); } + public void testCheckedTemplateWithCustomBasePath() throws Exception { + + // @CheckedTemplate(basePath="ItemResourceWithFragment") + //public class ItemTemplatesCustomBasePath { + // + // static native TemplateInstance items(List items); + // static native TemplateInstance items$id1(List items); + // static native TemplateInstance items3$id2(List items); + // static native TemplateInstance items3$(List items); + //} + + QuteJavaDiagnosticsParams params = new QuteJavaDiagnosticsParams(); + String javaFileUri = LSPIJUtils.toUri(module).resolve("src/main/java/org/acme/qute/ItemTemplatesCustomBasePath.java").toASCIIString(); + params.setUris(Arrays.asList(javaFileUri)); + + List publishDiagnostics = QuteSupportForJava.getInstance().diagnostics(params, + PsiUtilsLSImpl.getInstance(myProject), new EmptyProgressIndicator()); + assertEquals(1, publishDiagnostics.size()); + + List diagnostics = publishDiagnostics.get(0).getDiagnostics(); + assertEquals(2, diagnostics.size()); + + assertDiagnostic(diagnostics, // + new Diagnostic(r(11, 32, 11, 42), + "No template matching the path ItemResourceWithFragment/items3 could be found for: org.acme.qute.ItemTemplatesCustomBasePath", + DiagnosticSeverity.Error, "qute", QuteErrorCode.NoMatchingTemplate.name()), // + new Diagnostic(r(12, 32, 12, 39), + "Fragment [] not defined in template ItemResourceWithFragment/items3$", + DiagnosticSeverity.Error, "qute", QuteErrorCode.FragmentNotDefined.name())); + } + + public void testCheckedTemplateInInnerClassWithCustomBasePath() throws Exception { + + QuteJavaDiagnosticsParams params = new QuteJavaDiagnosticsParams(); + String javaFileUri = LSPIJUtils.toUri(module).resolve("src/main/java/org/acme/qute/ItemResourceWithCustomBasePath.java").toASCIIString(); + params.setUris(Arrays.asList(javaFileUri)); + + List publishDiagnostics = QuteSupportForJava.getInstance().diagnostics(params, + PsiUtilsLSImpl.getInstance(myProject), new EmptyProgressIndicator()); + assertEquals(1, publishDiagnostics.size()); + + List diagnostics = publishDiagnostics.get(0).getDiagnostics(); + assertEquals(2, diagnostics.size()); + + assertDiagnostic(diagnostics, // + new Diagnostic(r(23, 33, 23, 43), + "No template matching the path ItemResourceWithFragment/items3 could be found for: org.acme.qute.ItemResourceWithCustomBasePath$Templates", + DiagnosticSeverity.Error, "qute", QuteErrorCode.NoMatchingTemplate.name()), // + new Diagnostic(r(24, 33, 24, 40), + "Fragment [] not defined in template ItemResourceWithFragment/items3$", + DiagnosticSeverity.Error, "qute", QuteErrorCode.FragmentNotDefined.name()) + ); + } + + public static Range r(int line, int startChar, int endChar) { return r(line, startChar, line, endChar); } diff --git a/src/test/java/com/redhat/devtools/intellij/qute/psi/java/JavaDocumentLinkTest.java b/src/test/java/com/redhat/devtools/intellij/qute/psi/java/JavaDocumentLinkTest.java index 2b8e5bb49..1c09cb2cb 100644 --- a/src/test/java/com/redhat/devtools/intellij/qute/psi/java/JavaDocumentLinkTest.java +++ b/src/test/java/com/redhat/devtools/intellij/qute/psi/java/JavaDocumentLinkTest.java @@ -231,6 +231,36 @@ public void testCheckedTemplateInInnerClassWithFragment() throws Exception { "Open `src/main/resources/templates/ItemResourceWithFragment/items2$id2.html`")); } + public void testCheckedTemplateWithCustomBasePath() throws Exception { + + // @CheckedTemplate(basePath="ItemResourceWithFragment") + //public class ItemTemplatesCustomBasePath { + // + // static native TemplateInstance items(List items); + // static native TemplateInstance items$id1(List items); + // static native TemplateInstance items3$id2(List items); + // static native TemplateInstance items3$(List items); + //} + + QuteJavaDocumentLinkParams params = new QuteJavaDocumentLinkParams(); + String javaFileUri = LSPIJUtils.toUri(module).resolve("src/main/java/org/acme/qute/ItemTemplatesCustomBasePath.java").toASCIIString(); + params.setUri(javaFileUri); + + List links = QuteSupportForJava.getInstance().documentLink(params, PsiUtilsLSImpl.getInstance(myProject), + new EmptyProgressIndicator()); + assertEquals(3, links.size()); + + String templateFileUri = LSPIJUtils.toUri(module).resolve("src/main/resources/templates/ItemResourceWithFragment/items.html").toASCIIString(); + + assertDocumentLink(links, // + dl(r(9, 32, 9, 37), // + templateFileUri, "Open `src/main/resources/templates/ItemResourceWithFragment/items.html`"), // + dl(r(10, 32, 10, 41), // + templateFileUri, "Open `src/main/resources/templates/ItemResourceWithFragment/items.html`"), // + dl(r(11, 32, 11, 42), // + templateFileUri, "Create `src/main/resources/templates/ItemResourceWithFragment/items3.html`")); + } + public static Range r(int line, int startChar, int endChar) { return r(line, startChar, line, endChar); }