diff --git a/qute.jdt/com.redhat.qute.jdt/plugin.xml b/qute.jdt/com.redhat.qute.jdt/plugin.xml index ab915112c..aaf7918fa 100644 --- a/qute.jdt/com.redhat.qute.jdt/plugin.xml +++ b/qute.jdt/com.redhat.qute.jdt/plugin.xml @@ -82,6 +82,7 @@ + diff --git a/qute.jdt/com.redhat.qute.jdt/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplate.java b/qute.jdt/com.redhat.qute.jdt/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplate.java index 327794604..1b840f54d 100644 --- a/qute.jdt/com.redhat.qute.jdt/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplate.java +++ b/qute.jdt/com.redhat.qute.jdt/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplate.java @@ -28,6 +28,8 @@ public class DataModelTemplate extends DataModelBa private String templateUri; + private DataModelTemplateMatcher templateMatcher; + private String sourceField; private List> fragments; @@ -50,6 +52,14 @@ public void setTemplateUri(String templateUri) { this.templateUri = templateUri; } + public DataModelTemplateMatcher getTemplateMatcher() { + return templateMatcher; + } + + public void setTemplateMatcher(DataModelTemplateMatcher templateMatcher) { + this.templateMatcher = templateMatcher; + } + /** * Returns the Java source field where this data model template is defined and * null otherwise. @@ -131,6 +141,7 @@ public DataModelFragment getFragment(String fragmentId) { public String toString() { ToStringBuilder b = new ToStringBuilder(this); b.add("templateUri", this.templateUri); + b.add("templateMatcher", this.templateMatcher); b.add("sourceType", this.getSourceType()); b.add("sourceMethod", this.getSourceMethod()); b.add("sourceField", this.sourceField); diff --git a/qute.jdt/com.redhat.qute.jdt/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplateMatcher.java b/qute.jdt/com.redhat.qute.jdt/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplateMatcher.java new file mode 100644 index 000000000..ce722bedb --- /dev/null +++ b/qute.jdt/com.redhat.qute.jdt/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplateMatcher.java @@ -0,0 +1,47 @@ +/******************************************************************************* +* Copyright (c) 2024 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.qute.commons.datamodel; + +import java.util.List; + +import org.eclipse.xtext.xbase.lib.util.ToStringBuilder; + +/** + * Data model template matcher used to inject data parameters with patterns. + */ +public class DataModelTemplateMatcher { + + private List includes; + + public DataModelTemplateMatcher() { + + } + + public DataModelTemplateMatcher(List includes) { + setIncludes(includes); + } + + public List getIncludes() { + return includes; + } + + public void setIncludes(List includes) { + this.includes = includes; + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this); + b.add("includes", this.includes); + return b.toString(); + } +} diff --git a/qute.jdt/com.redhat.qute.jdt/src/main/java/com/redhat/qute/jdt/internal/extensions/roq/RoqDataModelProvider.java b/qute.jdt/com.redhat.qute.jdt/src/main/java/com/redhat/qute/jdt/internal/extensions/roq/RoqDataModelProvider.java new file mode 100644 index 000000000..24308acfe --- /dev/null +++ b/qute.jdt/com.redhat.qute.jdt/src/main/java/com/redhat/qute/jdt/internal/extensions/roq/RoqDataModelProvider.java @@ -0,0 +1,49 @@ +package com.redhat.qute.jdt.internal.extensions.roq; + +import java.util.Arrays; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.core.search.SearchMatch; +import org.eclipse.jdt.core.search.SearchPattern; + +import com.redhat.qute.commons.datamodel.DataModelParameter; +import com.redhat.qute.commons.datamodel.DataModelTemplate; +import com.redhat.qute.commons.datamodel.DataModelTemplateMatcher; +import com.redhat.qute.jdt.template.datamodel.AbstractDataModelProvider; +import com.redhat.qute.jdt.template.datamodel.SearchContext; + +public class RoqDataModelProvider extends AbstractDataModelProvider { + + @Override + public void collectDataModel(SearchMatch match, SearchContext context, IProgressMonitor monitor) { + + DataModelTemplate roqTemplate = new DataModelTemplate(); + roqTemplate.setTemplateMatcher(new DataModelTemplateMatcher(Arrays.asList("**/**"))); + + // site + DataModelParameter site = new DataModelParameter(); + site.setKey("site"); + site.setSourceType("io.quarkiverse.roq.frontmatter.runtime.model.Site"); + roqTemplate.addParameter(site); + + // page + DataModelParameter page = new DataModelParameter(); + page.setKey("page"); + page.setSourceType("io.quarkiverse.roq.frontmatter.runtime.model.Page"); + roqTemplate.addParameter(page); + + context.getDataModelProject().getTemplates().add(roqTemplate); + + } + + @Override + protected String[] getPatterns() { + return null; + } + + @Override + protected SearchPattern createSearchPattern(String pattern) { + return null; + } + +} diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/commons/datamodel/DataModelProject.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/commons/datamodel/DataModelProject.java index d6ea53739..b149a041b 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/commons/datamodel/DataModelProject.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/commons/datamodel/DataModelProject.java @@ -19,6 +19,7 @@ import com.redhat.qute.commons.datamodel.resolvers.NamespaceResolverInfo; import com.redhat.qute.commons.datamodel.resolvers.ValueResolverInfo; +import com.redhat.qute.project.datamodel.ExtendedDataModelTemplate; /** * Data model project hosts for a given Qute project: @@ -124,7 +125,7 @@ public String getUriWithoutExtension(String templateUri) { private T findDataModelTemplate(String templateUri, List templates) { Optional dataModelForTemplate = templates.stream() // - .filter(t -> templateUri.endsWith(t.getTemplateUri())) // + .filter(t -> ((ExtendedDataModelTemplate)t).matches(templateUri)) // .findFirst(); if (dataModelForTemplate.isPresent()) { return dataModelForTemplate.get(); diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplate.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplate.java index 327794604..1b840f54d 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplate.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplate.java @@ -28,6 +28,8 @@ public class DataModelTemplate extends DataModelBa private String templateUri; + private DataModelTemplateMatcher templateMatcher; + private String sourceField; private List> fragments; @@ -50,6 +52,14 @@ public void setTemplateUri(String templateUri) { this.templateUri = templateUri; } + public DataModelTemplateMatcher getTemplateMatcher() { + return templateMatcher; + } + + public void setTemplateMatcher(DataModelTemplateMatcher templateMatcher) { + this.templateMatcher = templateMatcher; + } + /** * Returns the Java source field where this data model template is defined and * null otherwise. @@ -131,6 +141,7 @@ public DataModelFragment getFragment(String fragmentId) { public String toString() { ToStringBuilder b = new ToStringBuilder(this); b.add("templateUri", this.templateUri); + b.add("templateMatcher", this.templateMatcher); b.add("sourceType", this.getSourceType()); b.add("sourceMethod", this.getSourceMethod()); b.add("sourceField", this.sourceField); diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplateMatcher.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplateMatcher.java new file mode 100644 index 000000000..ce722bedb --- /dev/null +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/commons/datamodel/DataModelTemplateMatcher.java @@ -0,0 +1,47 @@ +/******************************************************************************* +* Copyright (c) 2024 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.qute.commons.datamodel; + +import java.util.List; + +import org.eclipse.xtext.xbase.lib.util.ToStringBuilder; + +/** + * Data model template matcher used to inject data parameters with patterns. + */ +public class DataModelTemplateMatcher { + + private List includes; + + public DataModelTemplateMatcher() { + + } + + public DataModelTemplateMatcher(List includes) { + setIncludes(includes); + } + + public List getIncludes() { + return includes; + } + + public void setIncludes(List includes) { + this.includes = includes; + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this); + b.add("includes", this.includes); + return b.toString(); + } +} diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/project/datamodel/ExtendedDataModelTemplate.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/project/datamodel/ExtendedDataModelTemplate.java index 53b20cd21..2c7585480 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/project/datamodel/ExtendedDataModelTemplate.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/project/datamodel/ExtendedDataModelTemplate.java @@ -23,8 +23,11 @@ public class ExtendedDataModelTemplate extends DataModelTemplate implements DataModelSourceProvider { + private ExtendedDataModelTemplateMatcher templateMatcher; + public ExtendedDataModelTemplate(DataModelTemplate template) { super.setTemplateUri(template.getTemplateUri()); + super.setTemplateMatcher(template.getTemplateMatcher()); super.setSourceType(template.getSourceType()); super.setSourceMethod(template.getSourceMethod()); super.setSourceField(template.getSourceField()); @@ -64,4 +67,17 @@ public QuteJavaDefinitionParams toJavaDefinitionParams(String projectUri) { params.setSourceMethod(sourceMethod); return params; } + + public boolean matches(String templateUri) { + if (getTemplateUri() != null && templateUri.endsWith(getTemplateUri())) { + return true; + } + if (super.getTemplateMatcher() == null) { + return false; + } + if (templateMatcher == null) { + templateMatcher = new ExtendedDataModelTemplateMatcher(super.getTemplateMatcher().getIncludes()); + } + return templateMatcher.matches(templateUri); + } } diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/project/datamodel/ExtendedDataModelTemplateMatcher.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/project/datamodel/ExtendedDataModelTemplateMatcher.java new file mode 100644 index 000000000..f44cc1a25 --- /dev/null +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/project/datamodel/ExtendedDataModelTemplateMatcher.java @@ -0,0 +1,64 @@ +/******************************************************************************* +* Copyright (c) 2024 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.qute.project.datamodel; + +import java.net.URI; +import java.util.List; +import java.util.stream.Collectors; + +import com.redhat.qute.commons.FileUtils; +import com.redhat.qute.commons.datamodel.DataModelTemplateMatcher; +import com.redhat.qute.settings.PathPatternMatcher; + +/** + * Data model template matcher extension. + */ +public class ExtendedDataModelTemplateMatcher extends DataModelTemplateMatcher { + + private Boolean anyMatches; + + private List includes; + + public ExtendedDataModelTemplateMatcher(List includes) { + super(includes); + } + + public boolean matches(String templateFileUri) { + if (super.getIncludes() == null) { + return false; + } + if (includes == null && anyMatches == null) { + if (super.getIncludes().size() == 1 + && ("**".equals(super.getIncludes().get(0)) || "**/**".equals(super.getIncludes().get(0)))) { + anyMatches = true; + } else { + includes = super.getIncludes() // + .stream() // + .map(p -> new PathPatternMatcher(p)) // + .collect(Collectors.toList()); + } + } + + if (anyMatches != null && anyMatches) { + return true; + } + + URI uri = FileUtils.createUri(templateFileUri); + for (PathPatternMatcher include : includes) { + if (include.matches(uri)) { + return true; + } + } + return false; + } + +} diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteCodeLens.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteCodeLens.java index 3d958ff6d..4e6e5b48e 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteCodeLens.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteCodeLens.java @@ -91,7 +91,7 @@ private static void collectDataModelFoTemplateCodeLenses(DataModelSourceProvider private static void collectDataModelCodeLenses(Range range, DataModelSourceProvider templateDataModel, String projectUri, SharedSettings settings, List lenses, CancelChecker cancelChecker) { - if (templateDataModel == null || templateDataModel.getSourceType() == null) { + if (templateDataModel == null) { return; } @@ -100,20 +100,24 @@ private static void collectDataModelCodeLenses(Range range, DataModelSourceProvi boolean canSupportJavaDefinition = settings.getCommandCapabilities() .isCommandSupported(COMMAND_JAVA_DEFINITION); - // Method/Field which is bound with the template - String title = createCheckedTemplateTitle(templateDataModel); - Command command = !canSupportJavaDefinition ? new Command(title, "") - : new Command(title, COMMAND_JAVA_DEFINITION, - Arrays.asList(templateDataModel.toJavaDefinitionParams(projectUri))); - CodeLens codeLens = new CodeLens(range, command, null); - lenses.add(codeLens); + if (templateDataModel.getSourceType() == null) { + // Template with source type. + + // Method/Field which is bound with the template + String title = createCheckedTemplateTitle(templateDataModel); + Command command = !canSupportJavaDefinition ? new Command(title, "") + : new Command(title, COMMAND_JAVA_DEFINITION, + Arrays.asList(templateDataModel.toJavaDefinitionParams(projectUri))); + CodeLens codeLens = new CodeLens(range, command, null); + lenses.add(codeLens); + } // Parameters of the template List parameters = templateDataModel.getParameters(); if (parameters != null) { for (ExtendedDataModelParameter parameter : parameters) { String parameterTitle = createParameterTitle(parameter); - Command parameterCommand = !canSupportJavaDefinition ? new Command(title, "") + Command parameterCommand = !canSupportJavaDefinition ? new Command(parameterTitle, "") : new Command(parameterTitle, COMMAND_JAVA_DEFINITION, Arrays.asList(parameter.toJavaDefinitionParams(projectUri))); CodeLens parameterCodeLens = new CodeLens(range, parameterCommand, null); diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteDefinition.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteDefinition.java index 200cdb76a..9cdc9cdcc 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteDefinition.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteDefinition.java @@ -382,6 +382,9 @@ private CompletableFuture> findDefinitionFromParame cancelChecker.checkCanceled(); // Try to find in parameter model if (parameter != null) { + if (parameter.getSourceType() == null) { + return NO_DEFINITION; + } QuteJavaDefinitionParams params = parameter.toJavaDefinitionParams(project.getUri()); return findJavaDefinition(params, project, cancelChecker, () -> QutePositionUtility.createRange(part)); diff --git a/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/project/roq/RoqProject.java b/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/project/roq/RoqProject.java index 3c69a52c4..fec9b5774 100644 --- a/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/project/roq/RoqProject.java +++ b/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/project/roq/RoqProject.java @@ -11,6 +11,7 @@ *******************************************************************************/ package com.redhat.qute.project.roq; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -19,6 +20,7 @@ import com.redhat.qute.commons.datamodel.DataModelParameter; import com.redhat.qute.commons.datamodel.DataModelProject; import com.redhat.qute.commons.datamodel.DataModelTemplate; +import com.redhat.qute.commons.datamodel.DataModelTemplateMatcher; import com.redhat.qute.commons.datamodel.resolvers.NamespaceResolverInfo; import com.redhat.qute.commons.datamodel.resolvers.ValueResolverInfo; import com.redhat.qute.project.BaseQuteProject; @@ -49,7 +51,22 @@ protected void fillResolvedJavaTypes(List resolvedJavaType @Override protected void fillTemplates(List> templates) { + DataModelTemplate roqTemplate = new DataModelTemplate(); + roqTemplate.setTemplateMatcher(new DataModelTemplateMatcher(Arrays.asList("**/**"))); + // site + DataModelParameter site = new DataModelParameter(); + site.setKey("site"); + site.setSourceType("io.quarkiverse.roq.frontmatter.runtime.model.Site"); + roqTemplate.addParameter(site); + + // page + DataModelParameter page = new DataModelParameter(); + page.setKey("page"); + page.setSourceType("io.quarkiverse.roq.frontmatter.runtime.model.Page"); + roqTemplate.addParameter(page); + + templates.add(roqTemplate); } @Override diff --git a/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/services/diagnostics/roq/RoqDiagnosticsTest.java b/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/services/diagnostics/roq/RoqDiagnosticsTest.java index a5294bef4..054ad7f48 100644 --- a/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/services/diagnostics/roq/RoqDiagnosticsTest.java +++ b/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/services/diagnostics/roq/RoqDiagnosticsTest.java @@ -44,6 +44,12 @@ public void noErrorWithStringParameter() { testDiagnosticsFor(template); } + @Test + public void pageModelAutoImport() { + String template = "{page.date.format('yyyy, MMM dd')}"; + testDiagnosticsFor(template); + } + private static void testDiagnosticsFor(String value, Diagnostic... expected) { QuteAssert.testDiagnosticsFor(value, QuteAssert.FILE_URI, null, RoqProject.PROJECT_URI, QuteAssert.TEMPLATE_BASE_DIR, true, null, expected);