Skip to content

Commit

Permalink
fix: Qute template validation breaks when using Gradle
Browse files Browse the repository at this point in the history
Fixes #1237

Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr committed Oct 20, 2023
1 parent a1a9b8a commit bb7c0f5
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
/*******************************************************************************
* 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;
import com.intellij.openapi.module.ModuleUtilCore;
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;
Expand All @@ -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 = "<<defaulted>>";

private PsiQuteProjectUtils() {
}

public static ProjectInfo getProjectInfo(Module javaProject) {
String projectUri = getProjectURI(javaProject);
String templateBaseDir = getTemplateBaseDir(javaProject);
// Project dependencies
Set<Module> 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 = "<<defaulted>>";

private PsiQuteProjectUtils() {
}

public static ProjectInfo getProjectInfo(Module javaProject) {
String projectUri = getProjectURI(javaProject);
String templateBaseDir = getTemplateBaseDir(javaProject);
// Project dependencies
Set<Module> 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<VirtualFile> 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);
}
}

0 comments on commit bb7c0f5

Please sign in to comment.