From 896c54fd7656a3f0a55aef615e4579835c84036f Mon Sep 17 00:00:00 2001 From: Fred Bricon Date: Wed, 18 Oct 2023 19:14:49 +0200 Subject: [PATCH] fix: WIP let gradle main module find templates Signed-off-by: Fred Bricon --- .../qute/psi/QuteSupportForTemplate.java | 11 +++- .../AbstractQuteTemplateLinkCollector.java | 59 +++++++++++++++++-- .../qute/psi/utils/PsiQuteProjectUtils.java | 28 ++++++--- 3 files changed, 84 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/QuteSupportForTemplate.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/QuteSupportForTemplate.java index 88e505283..40d53207d 100644 --- a/src/main/java/com/redhat/devtools/intellij/qute/psi/QuteSupportForTemplate.java +++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/QuteSupportForTemplate.java @@ -18,6 +18,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -46,6 +47,8 @@ import java.util.concurrent.CancellationException; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static com.redhat.devtools.intellij.qute.psi.utils.PsiTypeUtils.findType; @@ -80,7 +83,7 @@ public List getProjects(Project project, IPsiUtils utils, ProgressI // Loop for module from the given project Module[] modules = ModuleManager.getInstance(project).getModules(); for (Module javaProject: modules) { - if (PsiQuteProjectUtils.hasQuteSupport(javaProject)) { + if (!isTestModule(javaProject) && PsiQuteProjectUtils.hasQuteSupport(javaProject)) { // It is a Qute project quteProjects.add(PsiQuteProjectUtils.getProjectInfo(javaProject)); } @@ -88,6 +91,12 @@ public List getProjects(Project project, IPsiUtils utils, ProgressI return quteProjects; } + private static final Pattern GRADLE_TEST_MODULE_PATTERN = Pattern.compile("\\..*test", Pattern.CASE_INSENSITIVE); + + private boolean isTestModule(Module module) { + return GRADLE_TEST_MODULE_PATTERN.matcher(module.getName()).find(); + } + /** * Returns the project information for the given project Uri. * 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 6cad3ba03..d7a63ccf4 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 @@ -29,10 +29,15 @@ import com.redhat.devtools.intellij.qute.psi.utils.PsiTypeUtils; import com.redhat.devtools.intellij.qute.psi.utils.TemplatePathInfo; import org.eclipse.lsp4j.Range; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; +import java.util.Arrays; +import java.util.Comparator; import java.util.concurrent.CancellationException; import java.util.logging.Level; import java.util.logging.Logger; @@ -203,8 +208,12 @@ private VirtualFile getTemplateFile(Module project, String templateFilePathWitho @Nullable private VirtualFile getVirtualFile(Module project, String templateFilePathWithoutExtension, String suffix) { + VirtualFile @NotNull [] roots = ModuleRootManager.getInstance(project).getContentRoots(); + String templatePath = templateFilePathWithoutExtension.endsWith(suffix)? templateFilePathWithoutExtension : templateFilePathWithoutExtension +suffix; + Arrays.sort(roots, Comparator.comparingInt(r -> r.getPath().length()));//put root with smallest path first (eliminates generated sources roots) for(VirtualFile root : ModuleRootManager.getInstance(project).getContentRoots()) { - VirtualFile templateFile = root.findFileByRelativePath(templateFilePathWithoutExtension + suffix); + URI templateUri = mergeURI(LSPIJUtils.toUri(root), templatePath); + VirtualFile templateFile = LSPIJUtils.findResourceFor(templateUri); if (templateFile != null && templateFile.exists()) { return templateFile; } @@ -213,14 +222,52 @@ private VirtualFile getVirtualFile(Module project, String templateFilePathWithou } protected String getVirtualFileUrl(Module project, String templateFilePathWithoutExtension, String suffix) { - try { - for(VirtualFile root : ModuleRootManager.getInstance(project).getContentRoots()) { - return new URL(LSPIJUtils.toUri(root).toURL(), templateFilePathWithoutExtension + suffix).toString(); - } - } catch (MalformedURLException e) {} + // Sort the roots based on the length of their paths + VirtualFile @NotNull [] roots = ModuleRootManager.getInstance(project).getContentRoots(); + String templatePath = templateFilePathWithoutExtension.endsWith(suffix)? templateFilePathWithoutExtension : templateFilePathWithoutExtension +suffix; + Arrays.sort(roots, Comparator.comparingInt(r -> r.getPath().length()));//put root with smallest path first (eliminates generated sources roots) + for(VirtualFile root : roots) { + + return mergeURI(LSPIJUtils.toUri(root), templatePath).toString(); + } return null; } + + /** + * Merge relative path with base URI. Eg. if base = file:///foo/bar/projectname/src/main + * and relativePath = src/main/resources/templates/foo.html, then the merged URI will be + * file:///foo/bar/projectname/src/main/resources/templates/foo.html + * + * @param base + * @param relativePath + * @return + */ + public static URI mergeURI(URI base, String relativePath) { + String basePath = base.getPath(); + if (basePath.endsWith("/")) { + basePath = basePath.substring(0, basePath.length()-1); + } + if (relativePath.startsWith("/")) { + relativePath = relativePath.substring(1); + } + String[] relativePathSegments = relativePath.split("/"); + StringBuilder prefix = new StringBuilder(); + for (String segment : relativePathSegments) { + if (segment.isEmpty()) { + continue; + } + if (prefix.length() > 0) { + prefix.append("/"); + } + prefix.append(segment); + if (basePath.endsWith(prefix.toString())){ + return base.resolve(relativePath.substring(prefix.length()+1)); + } + } + return base.resolve(relativePath); + } + protected String getRelativePath(String templateFilePath, VirtualFile templateFile, Module module) { if (templateFile != null) { for(VirtualFile root : ModuleRootManager.getInstance(module).getContentRoots()) { 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 abca3ba00..52d0dbb40 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 @@ -16,16 +16,13 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.vfs.VirtualFile; -import com.redhat.devtools.intellij.quarkus.QuarkusModuleUtil; 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; +import org.jetbrains.jps.model.java.JavaResourceRootType; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; /** @@ -55,14 +52,31 @@ public static ProjectInfo getProjectInfo(Module javaProject) { return new ProjectInfo(projectUri, projectDependencies .stream() .filter(projectDependency -> !javaProject.equals(projectDependency)) - .map(projectDependency -> LSPIJUtils.getProjectUri(projectDependency)) + .map(LSPIJUtils::getProjectUri) .collect(Collectors.toList()), templateBaseDir); } private static String getTemplateBaseDir(Module javaProject) { + List resourcesDirs = ModuleRootManager.getInstance(javaProject).getSourceRoots(JavaResourceRootType.RESOURCE); + if (!resourcesDirs.isEmpty()) { + for (var dir : resourcesDirs) { + var templatesDir = dir.findChild("templates"); + if (templatesDir != null && templatesDir.exists()) { + return LSPIJUtils.toUri(templatesDir).toASCIIString(); + } + } + return LSPIJUtils.toUri(resourcesDirs.get(0)).resolve("templates").toASCIIString(); + } return LSPIJUtils.toUri(javaProject).resolve(TEMPLATES_BASE_DIR).toASCIIString(); } + public List getSortedSourceRoots(Module module) { + VirtualFile @NotNull [] roots = ModuleRootManager.getInstance(module).getContentRoots(); + Arrays.sort(roots, Comparator.comparingInt(r -> r.getPath().length()));//put root with smallest path first (eliminates generated sources roots) + return null; + } + + /** * Returns the project URI of the given project. * @@ -108,7 +122,7 @@ public static TemplatePathInfo getTemplatePath(String basePath, String className if (!ignoreFragments) { int fragmentIndex = methodOrFieldName != null ? methodOrFieldName.lastIndexOf('$') : -1; if (fragmentIndex != -1) { - fragmentId = methodOrFieldName.substring(fragmentIndex + 1, methodOrFieldName.length()); + fragmentId = methodOrFieldName.substring(fragmentIndex + 1); methodOrFieldName = methodOrFieldName.substring(0, fragmentIndex); } }