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..ca3e2753f 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 @@ -39,10 +39,10 @@ import static com.redhat.devtools.intellij.qute.psi.internal.QuteJavaConstants.CHECKED_TEMPLATE_ANNOTATION; 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; +import static com.redhat.devtools.intellij.qute.psi.utils.PsiQuteProjectUtils.*; /** * Abstract class which collects {@link PsiMethod} or @@ -70,6 +70,7 @@ public abstract class AbstractQuteTemplateLinkCollector extends JavaRecursiveEle protected final PsiFile typeRoot; protected final IPsiUtils utils; protected final ProgressIndicator monitor; + private final @Nullable VirtualFile resourcesDir; private int levelTypeDecl; @@ -83,6 +84,7 @@ public AbstractQuteTemplateLinkCollector(PsiFile typeRoot, IPsiUtils utils, Prog this.utils = utils; this.monitor = monitor; this.levelTypeDecl = 0; + this.resourcesDir = findBestResourcesDirForTemplateBaseDir(utils.getModule()); } @Override @@ -180,7 +182,7 @@ private void collectTemplateLink(String basePath, PsiElement fieldOrMethod, PsiL getRelativePath(templatePathInfo.getTemplateUri(), templateFile, project), templatePathInfo.getFragmentId()); } else { - templateFile = getVirtualFile(project, templatePathInfo.getTemplateUri(), ""); + templateFile = getVirtualFile(resourcesDir, project, templatePathInfo.getTemplateUri(), ""); } collectTemplateLink(basePath, fieldOrMethod, locationAnnotation, type, className, fieldOrMethodName, location, templateFile, templatePathInfo); @@ -193,20 +195,23 @@ private void collectTemplateLink(String basePath, PsiElement fieldOrMethod, PsiL private VirtualFile getTemplateFile(Module project, String templateFilePathWithoutExtension) { for (String suffix : suffixes) { - VirtualFile templateFile = getVirtualFile(project, templateFilePathWithoutExtension, suffix); + VirtualFile templateFile = getVirtualFile(resourcesDir, project, templateFilePathWithoutExtension, suffix); if (templateFile != null) { return templateFile; } } - return getVirtualFile(project, templateFilePathWithoutExtension, PREFERRED_SUFFIX); + return getVirtualFile(resourcesDir, project, templateFilePathWithoutExtension, PREFERRED_SUFFIX); } @Nullable - private VirtualFile getVirtualFile(Module project, String templateFilePathWithoutExtension, String suffix) { - for(VirtualFile root : ModuleRootManager.getInstance(project).getContentRoots()) { - VirtualFile templateFile = root.findFileByRelativePath(templateFilePathWithoutExtension + suffix); - if (templateFile != null && templateFile.exists()) { - return templateFile; + private VirtualFile getVirtualFile(VirtualFile resourcesDir, Module project, String templateFilePathWithoutExtension, String suffix) { + if (resourcesDir != null) { + VirtualFile templatesDir = resourcesDir.findFileByRelativePath(TEMPLATES_FOLDER_NAME); + if (templatesDir != null && templatesDir.exists()) { + VirtualFile templateFile = templatesDir.findFileByRelativePath(templateFilePathWithoutExtension + suffix); + if (templateFile != null && templateFile.exists()) { + return templateFile; + } } } return null; @@ -231,7 +236,17 @@ protected String getRelativePath(String templateFilePath, VirtualFile templateFi } return templateFile.getPath(); } else { - return templateFilePath + PREFERRED_SUFFIX; + String basePath = RESOURCES_BASE_DIR; + if (resourcesDir != null) { + for(VirtualFile root : ModuleRootManager.getInstance(module).getContentRoots()) { + String path = VfsUtilCore.getRelativePath(resourcesDir, root); + if (path != null) { + basePath = path; + break; + } + } + } + return basePath + "/" + TEMPLATES_FOLDER_NAME + templateFilePath + PREFERRED_SUFFIX; } } protected Range createRange(PsiElement fieldOrMethod) { 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..4a8c33bb6 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 @@ -1,14 +1,14 @@ /******************************************************************************* -* Copyright (c) 2021 Red Hat Inc. and others. -* All rights reserved. This program and the accompanying materials -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Contributors: -* Red Hat Inc. - initial API and implementation -*******************************************************************************/ + * Copyright (c) 2021 Red Hat Inc. and others. + * All rights reserved. This program and the accompanying materials + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ package com.redhat.devtools.intellij.qute.psi.utils; import com.intellij.openapi.module.Module; @@ -16,13 +16,12 @@ 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; @@ -32,104 +31,128 @@ * JDT Qute utilities. * * @author Angelo ZERR - * */ 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() { - } - - public static ProjectInfo getProjectInfo(Module javaProject) { - String projectUri = getProjectURI(javaProject); - String templateBaseDir = getTemplateBaseDir(javaProject); - // Project dependencies - Set projectDependencies = new HashSet<>(); - ModuleUtilCore.getDependencies(javaProject, projectDependencies); - return new ProjectInfo(projectUri, projectDependencies - .stream() - .filter(projectDependency -> !javaProject.equals(projectDependency)) - .map(projectDependency -> LSPIJUtils.getProjectUri(projectDependency)) - .collect(Collectors.toList()), templateBaseDir); - } - - private static String getTemplateBaseDir(Module javaProject) { - return LSPIJUtils.toUri(javaProject).resolve(TEMPLATES_BASE_DIR).toASCIIString(); - } - - /** - * Returns the project URI of the given project. - * - * @param project the project - * @return the project URI of the given project. - */ - public static String getProjectURI(Module project) { - return LSPIJUtils.getProjectUri(project); - } - - /** - * Returns the project URI of the given project. - * - * @param project the project - * @return the project URI of the given project. - */ - public static String getProjectURI(Project project) { - return LSPIJUtils.getProjectUri(project); - } - - public static boolean hasQuteSupport(Module javaProject) { - return PsiTypeUtils.findType(javaProject, QuteJavaConstants.ENGINE_BUILDER_CLASS) != null; - } - - public static String getTemplatePath(String basePath, String className, String methodOrFieldName) { - StringBuilder path = new StringBuilder(TEMPLATES_BASE_DIR); - 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 basePath, String className, String methodOrFieldName, boolean ignoreFragments) { - String fragmentId = null; - StringBuilder templateUri = new StringBuilder(TEMPLATES_BASE_DIR); - 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; - if (fragmentIndex != -1) { - fragmentId = methodOrFieldName.substring(fragmentIndex + 1, methodOrFieldName.length()); - methodOrFieldName = methodOrFieldName.substring(0, fragmentIndex); - } - } - 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('/'); - } - } - - public static boolean isQuteTemplate(VirtualFile file, Module module) { - return file.getPath().contains("templates") && - ModuleRootManager.getInstance(module).getFileIndex().isInSourceContent(file); - } + public static final String RESOURCES_BASE_DIR = "src/main/resources"; + + public static final String TEMPLATES_FOLDER_NAME = "templates/"; + + /** + * Value for Qute annotations indicating behaviour should be using the default + */ + private static final String DEFAULTED = "<>"; + + private PsiQuteProjectUtils() { + } + + public static ProjectInfo getProjectInfo(Module javaProject) { + String projectUri = getProjectURI(javaProject); + String templateBaseDir = getTemplateBaseDir(javaProject); + // Project dependencies + Set projectDependencies = new HashSet<>(); + ModuleUtilCore.getDependencies(javaProject, projectDependencies); + return new ProjectInfo(projectUri, projectDependencies + .stream() + .filter(projectDependency -> !javaProject.equals(projectDependency)) + .map(LSPIJUtils::getProjectUri) + .collect(Collectors.toList()), templateBaseDir); + } + + private static String getTemplateBaseDir(Module javaProject) { + VirtualFile resourcesDir = findBestResourcesDirForTemplateBaseDir(javaProject); + if (resourcesDir != null) { + return LSPIJUtils.toUri(resourcesDir).resolve(TEMPLATES_FOLDER_NAME).toASCIIString(); + } + return LSPIJUtils.toUri(javaProject).resolve(RESOURCES_BASE_DIR).resolve(TEMPLATES_FOLDER_NAME).toASCIIString(); + } + + public static VirtualFile findBestResourcesDirForTemplateBaseDir(Module javaProject) { + List resourcesDirs = ModuleRootManager.getInstance(javaProject).getSourceRoots(JavaResourceRootType.RESOURCE); + if (!resourcesDirs.isEmpty()) { + for (var dir : resourcesDirs) { + var templatesDir = dir.findChild(TEMPLATES_FOLDER_NAME); + if (templatesDir != null && templatesDir.exists()) { + return dir; + } + } + return resourcesDirs.get(0); + } + VirtualFile[] roots = ModuleRootManager.getInstance(javaProject).getContentRoots(); + if (roots.length > 0) { + return roots[0]; + } + return javaProject.getModuleFile(); + } + + /** + * Returns the project URI of the given project. + * + * @param project the project + * @return the project URI of the given project. + */ + public static String getProjectURI(Module project) { + return LSPIJUtils.getProjectUri(project); + } + + /** + * Returns the project URI of the given project. + * + * @param project the project + * @return the project URI of the given project. + */ + public static String getProjectURI(Project project) { + return LSPIJUtils.getProjectUri(project); + } + + public static boolean hasQuteSupport(Module javaProject) { + return PsiTypeUtils.findType(javaProject, QuteJavaConstants.ENGINE_BUILDER_CLASS) != null; + } + + public static String getTemplatePath(String basePath, String className, String methodOrFieldName) { + StringBuilder path = new StringBuilder(); + 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 basePath, String className, String methodOrFieldName, boolean ignoreFragments) { + String fragmentId = null; + StringBuilder templateUri = new StringBuilder(); + 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; + if (fragmentIndex != -1) { + fragmentId = methodOrFieldName.substring(fragmentIndex + 1); + methodOrFieldName = methodOrFieldName.substring(0, fragmentIndex); + } + } + 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('/'); + } + } + + public static boolean isQuteTemplate(VirtualFile file, Module module) { + return file.getPath().contains("templates") && + ModuleRootManager.getInstance(module).getFileIndex().isInSourceContent(file); + } }