diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/InlayHint.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/InlayHint.java new file mode 100644 index 000000000..ba72c20db --- /dev/null +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/InlayHint.java @@ -0,0 +1,82 @@ +/******************************************************************************* +* Copyright (c) 2022 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.lsp4j.proposed; + +import java.util.List; + +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.eclipse.lsp4j.jsonrpc.validation.NonNull; +import org.eclipse.lsp4j.util.Preconditions; + +/** + * Inlay hint information. + * + * @since 3.17.0 - proposed state + */ +public class InlayHint { + + /** + * The position of this hint. + */ + @NonNull + private Position position; + + /** + * The label of this hint. A human readable string or an array of + * InlayHintLabelPart label parts. + * + * *Note* that neither the string nor the label part can be empty. + */ + @NonNull + private Either> label; + + /** + * The kind of this hint. Can be omitted in which case the client should fall + * back to a reasonable default. + */ + private InlayHintKind kind; + + public InlayHint(@NonNull Position position, Either> label) { + this.position = Preconditions.checkNotNull(position, "position"); + this.label = label; + + } + + public InlayHint() { + + } + + public Position getPosition() { + return position; + } + + public void setPosition(Position position) { + this.position = position; + } + + public Either> getLabel() { + return label; + } + + public void setLabel(Either> label) { + this.label = label; + } + + public InlayHintKind getKind() { + return kind; + } + + public void setKind(InlayHintKind kind) { + this.kind = kind; + } +} diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/InlayHintKind.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/InlayHintKind.java new file mode 100644 index 000000000..5acc0bc25 --- /dev/null +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/InlayHintKind.java @@ -0,0 +1,42 @@ +/******************************************************************************* +* Copyright (c) 2022 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.lsp4j.proposed; + +public enum InlayHintKind { + + /** + * An inlay hint that for a type annotation. + */ + Type(1), + + /** + * An inlay hint that is for a parameter. + */ + Parameter(2); + + private final int value; + + InlayHintKind(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static InlayHintKind forValue(int value) { + InlayHintKind[] allValues = InlayHintKind.values(); + if (value < 1 || value > allValues.length) + throw new IllegalArgumentException("Illegal enum value: " + value); + return allValues[value - 1]; + } +} diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/InlayHintLabelPart.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/InlayHintLabelPart.java new file mode 100644 index 000000000..1f26ead91 --- /dev/null +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/InlayHintLabelPart.java @@ -0,0 +1,18 @@ +/******************************************************************************* +* Copyright (c) 2022 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.lsp4j.proposed; + +public class InlayHintLabelPart { + + + +} diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/InlayHintParams.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/InlayHintParams.java new file mode 100644 index 000000000..c0bfabe58 --- /dev/null +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/InlayHintParams.java @@ -0,0 +1,108 @@ +/******************************************************************************* +* Copyright (c) 2022 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.lsp4j.proposed; + +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.TextDocumentIdentifier; +import org.eclipse.lsp4j.WorkDoneProgressParams; +import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.eclipse.lsp4j.jsonrpc.validation.NonNull; +import org.eclipse.lsp4j.util.Preconditions; +import org.eclipse.xtext.xbase.lib.Pure; + +public class InlayHintParams implements WorkDoneProgressParams { + + /** + * An optional token that a server can use to report work done progress. + */ + private Either workDoneToken; + + /** + * The document to format. + */ + @NonNull + private TextDocumentIdentifier textDocument; + + /** + * The visible document range for which inlay hints should be computed. + */ + @NonNull + private Range range; + + /** + * An optional token that a server can use to report work done progress. + */ + @Pure + @Override + public Either getWorkDoneToken() { + return this.workDoneToken; + } + + /** + * An optional token that a server can use to report work done progress. + */ + public void setWorkDoneToken(final Either workDoneToken) { + this.workDoneToken = workDoneToken; + } + + public void setWorkDoneToken(final String workDoneToken) { + if (workDoneToken == null) { + this.workDoneToken = null; + return; + } + this.workDoneToken = Either.forLeft(workDoneToken); + } + + /** + * The document to format. + */ + @Pure + @NonNull + public TextDocumentIdentifier getTextDocument() { + return this.textDocument; + } + + /** + * The document to format. + */ + public void setTextDocument(@NonNull final TextDocumentIdentifier textDocument) { + this.textDocument = Preconditions.checkNotNull(textDocument, "textDocument"); + } + + public void setWorkDoneToken(final Integer workDoneToken) { + if (workDoneToken == null) { + this.workDoneToken = null; + return; + } + this.workDoneToken = Either.forRight(workDoneToken); + } + + /** + * Returns the visible document range for which inlay hints should be computed. + * + * @return the visible document range for which inlay hints should be computed. + */ + @Pure + @NonNull + public Range getRange() { + return range; + } + + /** + * Set the visible document range for which inlay hints should be computed. + * + * @param range + */ + public void setRange(@NonNull Range range) { + this.range = Preconditions.checkNotNull(range, "range"); + } +} diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/QuteInlayHintProvider.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/QuteInlayHintProvider.java new file mode 100644 index 000000000..28e1559d8 --- /dev/null +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/lsp4j/proposed/QuteInlayHintProvider.java @@ -0,0 +1,26 @@ +/******************************************************************************* +* Copyright (c) 2022 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.lsp4j.proposed; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.lsp4j.jsonrpc.services.JsonRequest; + +public interface QuteInlayHintProvider { + + @JsonRequest("textDocument/inlayHint") + default CompletableFuture> inlayHint(InlayHintParams params) { + throw new UnsupportedOperationException(); + } + +} diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/AbstractTextDocumentService.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/AbstractTextDocumentService.java index a72b11132..1ef50ee79 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/AbstractTextDocumentService.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/AbstractTextDocumentService.java @@ -45,6 +45,8 @@ import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.eclipse.lsp4j.services.TextDocumentService; +import com.redhat.lsp4j.proposed.InlayHint; +import com.redhat.lsp4j.proposed.InlayHintParams; import com.redhat.qute.ls.commons.client.ExtendedClientCapabilities; import com.redhat.qute.settings.SharedSettings; @@ -160,6 +162,10 @@ public CompletableFuture linkedEditingRange(LinkedEditingRa return CompletableFuture.completedFuture(null); } + public CompletableFuture> inlayHint(InlayHintParams params) { + return CompletableFuture.completedFuture(null); + } + public boolean isHierarchicalDocumentSymbolSupport() { return hierarchicalDocumentSymbolSupport; } diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/QuteLanguageServer.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/QuteLanguageServer.java index 317577efd..eb6d55974 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/QuteLanguageServer.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/QuteLanguageServer.java @@ -31,6 +31,9 @@ import org.eclipse.lsp4j.services.LanguageServer; import org.eclipse.lsp4j.services.TextDocumentService; +import com.redhat.lsp4j.proposed.InlayHint; +import com.redhat.lsp4j.proposed.InlayHintParams; +import com.redhat.lsp4j.proposed.QuteInlayHintProvider; import com.redhat.qute.commons.JavaTypeInfo; import com.redhat.qute.commons.ProjectInfo; import com.redhat.qute.commons.QuteJavaDefinitionParams; @@ -73,7 +76,7 @@ */ public class QuteLanguageServer implements LanguageServer, ProcessLanguageServer, QuteLanguageServerAPI, QuteProjectInfoProvider, QuteJavaTypesProvider, QuteResolvedJavaTypeProvider, QuteJavaDefinitionProvider, - QuteDataModelProjectProvider, QuteUserTagProvider { + QuteDataModelProjectProvider, QuteUserTagProvider, QuteInlayHintProvider { private static final Logger LOGGER = Logger.getLogger(QuteLanguageServer.class.getName()); @@ -93,7 +96,7 @@ public class QuteLanguageServer implements LanguageServer, ProcessLanguageServer public QuteLanguageServer() { this.sharedSettings = new SharedSettings(); - this.projectRegistry = new QuteProjectRegistry(this, this, this, this,this); + this.projectRegistry = new QuteProjectRegistry(this, this, this, this, this); this.dataModelCache = new JavaDataModelCache(projectRegistry); this.quteLanguageService = new QuteLanguageService(dataModelCache); this.textDocumentService = new QuteTextDocumentService(this); @@ -151,10 +154,19 @@ public synchronized void updateSettings(Object initializationOptionsSettings) { // Update shared settings from the new client settings SettingsUpdateState result = QuteGeneralClientSettings.update(getSharedSettings(), clientSettings); + if (result.isCodeLensSettingsChanged()) { + // Some codelens settings changed, ask the client to refresh all code lenses. + getLanguageClient().refreshCodeLenses(); + } + if (result.isInlayHintSettingsChanged()) { + // Some inlay hint settings changed, ask the client to refresh all inlay hints. + getLanguageClient().refreshInlayHints(); + } if (result.isValidationSettingsChanged()) { // Some validation settings changed textDocumentService.validationSettingsChanged(); } + } } @@ -261,4 +273,9 @@ public CompletableFuture> getUserTags(QuteUserTagParams params public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) { textDocumentService.didChangeWatchedFiles(params); } + + @Override + public CompletableFuture> inlayHint(InlayHintParams params) { + return textDocumentService.inlayHint(params); + } } diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/QuteTextDocumentService.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/QuteTextDocumentService.java index 62053fbb7..6929a74c4 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/QuteTextDocumentService.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/QuteTextDocumentService.java @@ -52,6 +52,8 @@ import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.eclipse.lsp4j.services.TextDocumentService; +import com.redhat.lsp4j.proposed.InlayHint; +import com.redhat.lsp4j.proposed.InlayHintParams; import com.redhat.qute.commons.datamodel.JavaDataModelChangeEvent; import com.redhat.qute.ls.commons.client.ExtendedClientCapabilities; import com.redhat.qute.ls.java.JavaFileTextDocumentService; @@ -233,7 +235,15 @@ public CompletableFuture linkedEditingRange(LinkedEditingRa return CompletableFuture.completedFuture(null); } - private TextDocumentService getTextDocumentService(TextDocumentIdentifier document) { + public CompletableFuture> inlayHint(InlayHintParams params) { + AbstractTextDocumentService service = getTextDocumentService(params.getTextDocument()); + if (service != null) { + return service.inlayHint(params); + } + return CompletableFuture.completedFuture(null); + } + + private AbstractTextDocumentService getTextDocumentService(TextDocumentIdentifier document) { String fileExtension = getFileExtension(document); if ("java".equals(fileExtension) || "class".equals(fileExtension)) { return javaFileTextDocumentService; diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/api/QuteLanguageClientAPI.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/api/QuteLanguageClientAPI.java index 8cb6d5f97..0b335b7ac 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/api/QuteLanguageClientAPI.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/api/QuteLanguageClientAPI.java @@ -11,6 +11,9 @@ *******************************************************************************/ package com.redhat.qute.ls.api; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.lsp4j.jsonrpc.services.JsonRequest; import org.eclipse.lsp4j.services.LanguageClient; /** @@ -22,4 +25,11 @@ public interface QuteLanguageClientAPI extends LanguageClient, QuteJavaTypesProvider, QuteResolvedJavaTypeProvider, QuteJavaDefinitionProvider, QuteProjectInfoProvider, QuteDataModelProjectProvider, QuteUserTagProvider, QuteJavaCodeLensProvider, QuteJavaDiagnosticsProvider, QuteJavaDocumentLinkProvider { + + // TODO : remove this method when LSP4J will provide InlayHint support. See + // https://github.com/eclipse/lsp4j/issues/570 + @JsonRequest("workspace/inlayHint/refresh") + default CompletableFuture refreshInlayHints() { + throw new UnsupportedOperationException(); + } } \ No newline at end of file diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/template/TemplateFileTextDocumentService.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/template/TemplateFileTextDocumentService.java index fd37510f1..bd29d66b7 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/template/TemplateFileTextDocumentService.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/template/TemplateFileTextDocumentService.java @@ -53,6 +53,8 @@ import org.eclipse.lsp4j.jsonrpc.CancelChecker; import org.eclipse.lsp4j.jsonrpc.messages.Either; +import com.redhat.lsp4j.proposed.InlayHint; +import com.redhat.lsp4j.proposed.InlayHintParams; import com.redhat.qute.commons.datamodel.JavaDataModelChangeEvent; import com.redhat.qute.ls.AbstractTextDocumentService; import com.redhat.qute.ls.QuteLanguageServer; @@ -237,6 +239,15 @@ public CompletableFuture linkedEditingRange(LinkedEditingRa }); } + @Override + public CompletableFuture> inlayHint(InlayHintParams params) { + return computeModelAsync2(getDocument(params.getTextDocument().getUri()).getModel(), + (cancelChecker, template) -> { + return getQuteLanguageService().getInlayHint(template, params.getRange(), + sharedSettings.getInlayHintSettings(), cancelChecker); + }); + } + private QuteLanguageService getQuteLanguageService() { return quteLanguageServer.getQuarkusLanguageService(); } @@ -252,8 +263,8 @@ private void triggerValidationFor(QuteTextDocument document) { // Collect diagnostics ResolvingJavaTypeContext resolvingJavaTypeContext = new ResolvingJavaTypeContext(template); List diagnostics = getQuteLanguageService().doDiagnostics(template, - getSharedSettings().getValidationSettings(template.getUri()), - resolvingJavaTypeContext, () -> template.checkCanceled()); + getSharedSettings().getValidationSettings(template.getUri()), resolvingJavaTypeContext, + () -> template.checkCanceled()); // Diagnostics has been collected, before diagnostics publishing, check if the // document has changed since diagnostics collect. @@ -364,9 +375,9 @@ public void dataModelChanged(JavaDataModelChangeEvent event) { public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) { // trigger validation for all opened Qute template files - documents.all().stream().forEach(document -> { - triggerValidationFor((QuteTextDocument) document); - }); + documents.all().stream().forEach(document -> { + triggerValidationFor((QuteTextDocument) document); + }); } } \ No newline at end of file diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteInlayHint.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteInlayHint.java new file mode 100644 index 000000000..c99b49915 --- /dev/null +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteInlayHint.java @@ -0,0 +1,58 @@ +/******************************************************************************* +* Copyright (c) 2022 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.services; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.jsonrpc.CancelChecker; + +import com.redhat.lsp4j.proposed.InlayHint; +import com.redhat.qute.parser.template.Template; +import com.redhat.qute.project.datamodel.JavaDataModelCache; +import com.redhat.qute.services.inlayhint.InlayHintASTVistor; +import com.redhat.qute.settings.QuteInlayHintSettings; + +/** + * Qute inlay hint support. + * + * @author Angelo ZERR + * + */ +public class QuteInlayHint { + + private static CompletableFuture> NO_INLAY_HINT = CompletableFuture + .completedFuture(Collections.emptyList()); + + private final JavaDataModelCache javaCache; + + public QuteInlayHint(JavaDataModelCache javaCache) { + this.javaCache = javaCache; + } + + public CompletableFuture> getInlayHint(Template template, Range range, + QuteInlayHintSettings inlayHintSettings, CancelChecker cancelChecker) { + QuteInlayHintSettings settings = inlayHintSettings != null ? inlayHintSettings : QuteInlayHintSettings.DEFAULT; + if (!settings.isEnabled()) { + return NO_INLAY_HINT; + } + return javaCache.getDataModelTemplate(template) // + .thenApply(templateDataModel -> { + InlayHintASTVistor visitor = new InlayHintASTVistor(javaCache, range, settings, cancelChecker); + template.accept(visitor); + return visitor.getInlayHints(); + }); + } + +} diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteLanguageService.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteLanguageService.java index 7bf21ed50..f22bec4b3 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteLanguageService.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/QuteLanguageService.java @@ -32,6 +32,7 @@ import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.jsonrpc.CancelChecker; +import com.redhat.lsp4j.proposed.InlayHint; import com.redhat.qute.ls.commons.snippets.Snippet; import com.redhat.qute.ls.commons.snippets.SnippetRegistry; import com.redhat.qute.ls.commons.snippets.SnippetRegistryProvider; @@ -40,6 +41,7 @@ import com.redhat.qute.services.diagnostics.ResolvingJavaTypeContext; import com.redhat.qute.settings.QuteCompletionSettings; import com.redhat.qute.settings.QuteFormattingSettings; +import com.redhat.qute.settings.QuteInlayHintSettings; import com.redhat.qute.settings.QuteValidationSettings; import com.redhat.qute.settings.SharedSettings; @@ -63,6 +65,8 @@ public class QuteLanguageService implements SnippetRegistryProvider { private final QuteLinkedEditing linkedEditing; private final QuteReference reference; + private final QuteInlayHint inlayHint; + private SnippetRegistry coreTagSnippetRegistry; public QuteLanguageService(JavaDataModelCache javaCache) { @@ -77,6 +81,7 @@ public QuteLanguageService(JavaDataModelCache javaCache) { this.diagnostics = new QuteDiagnostics(javaCache); this.reference = new QuteReference(); this.linkedEditing = new QuteLinkedEditing(); + this.inlayHint = new QuteInlayHint(javaCache); } /** @@ -155,6 +160,11 @@ public LinkedEditingRanges findLinkedEditingRanges(Template template, Position p return linkedEditing.findLinkedEditingRanges(template, position, cancelChecker); } + public CompletableFuture> getInlayHint(Template template, Range range, QuteInlayHintSettings inlayHintSettings, + CancelChecker cancelChecker) { + return inlayHint.getInlayHint(template, range, inlayHintSettings, cancelChecker); + } + /** * Returns the core tag (ex : #for, #if, etc) snippet registry. * @@ -174,4 +184,5 @@ private synchronized void loadCoreTagSnippetRegistry() { } coreTagSnippetRegistry = new SnippetRegistry(); } + } diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/inlayhint/InlayHintASTVistor.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/inlayhint/InlayHintASTVistor.java new file mode 100644 index 000000000..5d2ac9a9a --- /dev/null +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/services/inlayhint/InlayHintASTVistor.java @@ -0,0 +1,166 @@ +/******************************************************************************* +* Copyright (c) 2022 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.services.inlayhint; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.jsonrpc.CancelChecker; +import org.eclipse.lsp4j.jsonrpc.messages.Either; + +import com.redhat.lsp4j.proposed.InlayHint; +import com.redhat.qute.commons.ResolvedJavaTypeInfo; +import com.redhat.qute.parser.expression.MethodPart; +import com.redhat.qute.parser.template.ASTVisitor; +import com.redhat.qute.parser.template.Expression; +import com.redhat.qute.parser.template.Parameter; +import com.redhat.qute.parser.template.Section; +import com.redhat.qute.parser.template.Template; +import com.redhat.qute.parser.template.sections.CustomSection; +import com.redhat.qute.parser.template.sections.ForSection; +import com.redhat.qute.parser.template.sections.LetSection; +import com.redhat.qute.parser.template.sections.SetSection; +import com.redhat.qute.project.datamodel.JavaDataModelCache; +import com.redhat.qute.settings.QuteInlayHintSettings; + +/** + * AST visitor used to show inferred Java type for section/method parameter as + * inlay hint. + * + * @author Angelo ZERR + * + */ +public class InlayHintASTVistor extends ASTVisitor { + + private final JavaDataModelCache javaCache; + private final Range range; + private final QuteInlayHintSettings inlayHintSettings; + private final List inlayHints; + + public InlayHintASTVistor(JavaDataModelCache javaCache, Range range, QuteInlayHintSettings inlayHintSettings, + CancelChecker cancelChecker) { + this.javaCache = javaCache; + this.range = range; + this.inlayHintSettings = inlayHintSettings; + this.inlayHints = new ArrayList(); + } + + public List getInlayHints() { + return inlayHints; + } + + @Override + public boolean visit(ForSection node) { + if (inlayHintSettings.isShowSectionParameterType()) { + // {#for item[:Item] in items} + Parameter aliasParameter = node.getAliasParameter(); + if (aliasParameter != null) { + Parameter iterableParameter = node.getIterableParameter(); + if (iterableParameter != null) { + Template template = node.getOwnerTemplate(); + String projectUri = template.getProjectUri(); + ResolvedJavaTypeInfo javaType = getJavaType(iterableParameter, projectUri); + if (javaType != null && javaType.isIterable()) { + javaType = javaCache.resolveJavaType(javaType.getIterableOf(), projectUri).getNow(null); + if (javaType != null) { + createInlayHint(aliasParameter, javaType, template); + } + } + } + } + } + return super.visit(node); + } + + @Override + public boolean visit(LetSection node) { + createInlayHintParametersSection(node); + return true; + } + + public boolean visit(SetSection node) { + createInlayHintParametersSection(node); + return true; + } + + public boolean visit(CustomSection node) { + createInlayHintParametersSection(node); + return true; + } + + private void createInlayHintParametersSection(Section node) { + if (!inlayHintSettings.isShowSectionParameterType()) { + return; + } + // {#let user[:User]=item.owner } + // {#set user[:User]=item.owner } + // {#form id[:String]=item.id } + // {#form item.id[:String] } + Template template = node.getOwnerTemplate(); + String projectUri = template.getProjectUri(); + List parameters = node.getParameters(); + for (Parameter parameter : parameters) { + createJavaTypeInlayHint(parameter, template, projectUri); + } + } + + @Override + public boolean visit(MethodPart node) { + Template template = node.getOwnerTemplate(); + String projectUri = template.getProjectUri(); + if (inlayHintSettings.isShowMethodParameterType()) { + List parameters = node.getParameters(); + for (Parameter parameter : parameters) { + createJavaTypeInlayHint(parameter, template, projectUri); + } + } + return super.visit(node); + } + + private void createJavaTypeInlayHint(Parameter parameter, Template template, String projectUri) { + ResolvedJavaTypeInfo javaType = getJavaType(parameter, projectUri); + if (javaType == null) { + return; + } + createInlayHint(parameter, javaType, template); + } + + private void createInlayHint(Parameter parameter, ResolvedJavaTypeInfo javaType, Template template) { + try { + InlayHint hint = new InlayHint(); + hint.setLabel(Either.forLeft(":" + javaType.getJavaElementSimpleType())); + int end = parameter.hasValueAssigned() ? parameter.getEndName() : parameter.getEnd(); + Position position = template.positionAt(end); + hint.setPosition(position); + inlayHints.add(hint); + } catch (Exception e) { + + } + } + + private ResolvedJavaTypeInfo getJavaType(Parameter parameter, String projectUri) { + if (projectUri == null) { + return null; + } + Expression expression = parameter.getJavaTypeExpression(); + if (expression == null) { + return null; + } + String literalJavaType = expression.getLiteralJavaType(); + if (literalJavaType != null) { + return javaCache.resolveJavaType(literalJavaType, projectUri).getNow(null); + } + return javaCache.resolveJavaType(parameter, projectUri).getNow(null); + } +} diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/BaseSettings.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/BaseSettings.java index 09ffa87be..c97257314 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/BaseSettings.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/BaseSettings.java @@ -19,10 +19,34 @@ */ public class BaseSettings { + private final QuteCodeLensSettings codeLensSettings; + + private final QuteInlayHintSettings inlayHintSettings; + private final QuteValidationSettings validationSettings; public BaseSettings() { this.validationSettings = new QuteValidationSettings(); + this.codeLensSettings = new QuteCodeLensSettings(); + this.inlayHintSettings = new QuteInlayHintSettings(); + } + + /** + * Returns the codeLens settings. + * + * @return the codeLens settings. + */ + public QuteCodeLensSettings getCodeLensSettings() { + return codeLensSettings; + } + + /** + * Returns the inlay hint settings. + * + * @return the inlay hint settings. + */ + public QuteInlayHintSettings getInlayHintSettings() { + return inlayHintSettings; } /** diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/QuteCodeLensSettings.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/QuteCodeLensSettings.java index 391a7c717..93f050148 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/QuteCodeLensSettings.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/QuteCodeLensSettings.java @@ -27,4 +27,30 @@ public boolean isEnabled() { return enabled; } + public void update(QuteCodeLensSettings newCodeLens) { + this.setEnabled(newCodeLens.isEnabled()); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (enabled ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + QuteCodeLensSettings other = (QuteCodeLensSettings) obj; + if (enabled != other.enabled) + return false; + return true; + } + } diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/QuteGeneralClientSettings.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/QuteGeneralClientSettings.java index a2042b9c9..52c86dd78 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/QuteGeneralClientSettings.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/QuteGeneralClientSettings.java @@ -34,8 +34,20 @@ public class QuteGeneralClientSettings { private Map workspaceFolders; + private QuteCodeLensSettings codeLens; + + private QuteInlayHintSettings inlayHint; + private QuteValidationSettings validation; + public QuteCodeLensSettings getCodeLens() { + return codeLens; + } + + public QuteInlayHintSettings getInlayHint() { + return inlayHint; + } + /** * Returns the validation settings. * @@ -45,6 +57,14 @@ public QuteValidationSettings getValidation() { return validation; } + public void setCodeLens(QuteCodeLensSettings codeLens) { + this.codeLens = codeLens; + } + + public void setInlayHint(QuteInlayHintSettings inlayHint) { + this.inlayHint = inlayHint; + } + /** * Set the validation settings. * @@ -80,8 +100,15 @@ public static class SettingsUpdateState { private final boolean validationSettingsChanged; - public SettingsUpdateState(boolean validationChanged) { - this.validationSettingsChanged = validationChanged; + private final boolean codeLensSettingsChanged; + + private final boolean inlayHintSettingsChanged; + + public SettingsUpdateState(boolean validationSettingsChanged, boolean codeLensSettingsChanged, + boolean inlayHintSettingsChanged) { + this.validationSettingsChanged = validationSettingsChanged; + this.codeLensSettingsChanged = codeLensSettingsChanged; + this.inlayHintSettingsChanged = inlayHintSettingsChanged; } /** @@ -93,6 +120,24 @@ public boolean isValidationSettingsChanged() { return validationSettingsChanged; } + /** + * Returns true if code lens settings changed and false otherwise. + * + * @return true if code lens settings changed and false otherwise. + */ + public boolean isCodeLensSettingsChanged() { + return codeLensSettingsChanged; + } + + /** + * Returns true if inlay hint settings changed and false otherwise. + * + * @return true if inlay hint settings changed and false otherwise. + */ + public boolean isInlayHintSettingsChanged() { + return inlayHintSettingsChanged; + } + } /** @@ -105,12 +150,77 @@ public boolean isValidationSettingsChanged() { */ public static SettingsUpdateState update(SharedSettings sharedSettings, QuteGeneralClientSettings clientSettings) { Map workspaceFolders = clientSettings.getWorkspaceFolders(); + boolean workspaceChanged = sharedSettings + .cleanWorkspaceFolderSettings(workspaceFolders != null ? workspaceFolders.keySet() : null); + + // Update code lens settings + boolean codeLensSettingsChanged = updateCodeLensSettings(sharedSettings, clientSettings); + if (workspaceChanged) { + codeLensSettingsChanged = true; + } + + // Update inlay hint settings + boolean inlayHintSettingsChanged = updateInlayHintSettings(sharedSettings, clientSettings); + if (workspaceChanged) { + inlayHintSettingsChanged = true; + } + // Update validation settings boolean validationSettingsChanged = updateValidationSettings(sharedSettings, clientSettings); - if (sharedSettings.cleanWorkspaceFolderSettings(workspaceFolders != null ? workspaceFolders.keySet() : null)) { + if (workspaceChanged) { validationSettingsChanged = true; } - return new SettingsUpdateState(validationSettingsChanged); + return new SettingsUpdateState(validationSettingsChanged, codeLensSettingsChanged, inlayHintSettingsChanged); + } + + private static boolean updateCodeLensSettings(SharedSettings sharedSettings, + QuteGeneralClientSettings clientSettings) { + // Global codeLens settings + boolean codeLensSettingsChanged = updateCodeLensSettings(sharedSettings, clientSettings.getCodeLens()); + // Workspace folder codeLens settings + Map workspaceFolders = clientSettings.getWorkspaceFolders(); + if (workspaceFolders != null) { + for (Map.Entry entry : workspaceFolders + .entrySet()) { + String workspaceFolderUri = entry.getKey(); + BaseSettings settings = sharedSettings.getWorkspaceFolderSettings(workspaceFolderUri); + codeLensSettingsChanged |= updateCodeLensSettings(settings, entry.getValue().getCodeLens()); + } + } + return codeLensSettingsChanged; + } + + private static boolean updateCodeLensSettings(BaseSettings sharedSettings, QuteCodeLensSettings codeLens) { + if (codeLens != null && !codeLens.equals(sharedSettings.getCodeLensSettings())) { + sharedSettings.getCodeLensSettings().update(codeLens); + return true; + } + return false; + } + + private static boolean updateInlayHintSettings(SharedSettings sharedSettings, + QuteGeneralClientSettings clientSettings) { + // Global inlayHint settings + boolean inlayHintSettingsChanged = updateInlayHintSettings(sharedSettings, clientSettings.getInlayHint()); + // Workspace folder inlayHint settings + Map workspaceFolders = clientSettings.getWorkspaceFolders(); + if (workspaceFolders != null) { + for (Map.Entry entry : workspaceFolders + .entrySet()) { + String workspaceFolderUri = entry.getKey(); + BaseSettings settings = sharedSettings.getWorkspaceFolderSettings(workspaceFolderUri); + inlayHintSettingsChanged |= updateInlayHintSettings(settings, entry.getValue().getInlayHint()); + } + } + return inlayHintSettingsChanged; + } + + private static boolean updateInlayHintSettings(BaseSettings sharedSettings, QuteInlayHintSettings inlayHint) { + if (inlayHint != null && !inlayHint.equals(sharedSettings.getInlayHintSettings())) { + sharedSettings.getInlayHintSettings().update(inlayHint); + return true; + } + return false; } private static boolean updateValidationSettings(SharedSettings sharedSettings, @@ -137,4 +247,5 @@ private static boolean updateValidationSettings(BaseSettings sharedSettings, Qut } return false; } + } \ No newline at end of file diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/QuteInlayHintSettings.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/QuteInlayHintSettings.java new file mode 100644 index 000000000..09377484b --- /dev/null +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/QuteInlayHintSettings.java @@ -0,0 +1,94 @@ +/******************************************************************************* +* Copyright (c) 2022 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.settings; + +/** + * Qute inlay hint settings. + * + * @author Angelo ZERR + * + */ +public class QuteInlayHintSettings { + + public static final QuteInlayHintSettings DEFAULT = new QuteInlayHintSettings(); + + private boolean enabled; + + private boolean showSectionParameterType; + + private boolean showMethodParameterType; + + public QuteInlayHintSettings() { + setEnabled(true); + setShowSectionParameterType(true); + setShowMethodParameterType(true); + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean isShowSectionParameterType() { + return showSectionParameterType; + } + + public void setShowSectionParameterType(boolean showSectionParameterType) { + this.showSectionParameterType = showSectionParameterType; + } + + public boolean isShowMethodParameterType() { + return showMethodParameterType; + } + + public void setShowMethodParameterType(boolean showMethodParameterType) { + this.showMethodParameterType = showMethodParameterType; + } + + public void update(QuteInlayHintSettings newInlayHint) { + this.setEnabled(newInlayHint.isEnabled()); + this.setShowSectionParameterType(newInlayHint.isShowSectionParameterType()); + this.setShowMethodParameterType(newInlayHint.isShowMethodParameterType()); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (enabled ? 1231 : 1237); + result = prime * result + (showMethodParameterType ? 1231 : 1237); + result = prime * result + (showSectionParameterType ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + QuteInlayHintSettings other = (QuteInlayHintSettings) obj; + if (enabled != other.enabled) + return false; + if (showMethodParameterType != other.showMethodParameterType) + return false; + if (showSectionParameterType != other.showSectionParameterType) + return false; + return true; + } + +} diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/SharedSettings.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/SharedSettings.java index 735426e07..457021892 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/SharedSettings.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/SharedSettings.java @@ -25,7 +25,6 @@ */ public class SharedSettings extends BaseSettings { private final QuteCompletionSettings completionSettings; - private final QuteCodeLensSettings codeLensSettings; private final QuteFormattingSettings formattingSettings; private final QuteHoverSettings hoverSettings; private final QuteCommandCapabilities commandCapabilities; @@ -35,7 +34,6 @@ public class SharedSettings extends BaseSettings { public SharedSettings() { super(); this.completionSettings = new QuteCompletionSettings(); - this.codeLensSettings = new QuteCodeLensSettings(); this.formattingSettings = new QuteFormattingSettings(); this.hoverSettings = new QuteHoverSettings(); this.commandCapabilities = new QuteCommandCapabilities(); @@ -50,15 +48,6 @@ public QuteCompletionSettings getCompletionSettings() { return completionSettings; } - /** - * Returns the codeLens settings. - * - * @return the codeLens settings. - */ - public QuteCodeLensSettings getCodeLensSettings() { - return codeLensSettings; - } - /** * Returns the formatting settings. * diff --git a/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/QuteAssert.java b/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/QuteAssert.java index c1a042340..5f2449a62 100644 --- a/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/QuteAssert.java +++ b/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/QuteAssert.java @@ -62,6 +62,7 @@ import org.eclipse.lsp4j.WorkspaceEdit; import org.eclipse.lsp4j.jsonrpc.messages.Either; +import com.redhat.lsp4j.proposed.InlayHint; import com.redhat.qute.commons.ProjectInfo; import com.redhat.qute.ls.commons.BadLocationException; import com.redhat.qute.ls.commons.TextDocument; @@ -80,6 +81,7 @@ import com.redhat.qute.services.diagnostics.ResolvingJavaTypeContext; import com.redhat.qute.settings.QuteCompletionSettings; import com.redhat.qute.settings.QuteFormattingSettings; +import com.redhat.qute.settings.QuteInlayHintSettings; import com.redhat.qute.settings.QuteValidationSettings; import com.redhat.qute.settings.SharedSettings; import com.redhat.qute.utils.StringUtils; @@ -259,16 +261,6 @@ private static CompletionItem c(String label, TextEdit textEdit, String filterTe return item; } - public static Range r(int line, int startChar, int endChar) { - return r(line, startChar, line, endChar); - } - - public static Range r(int startLine, int startChar, int endLine, int endChar) { - Position start = new Position(startLine, startChar); - Position end = new Position(endLine, endChar); - return new Range(start, end); - } - // ------------------- Diagnostics assert public static void testDiagnosticsFor(String value, Diagnostic... expected) { @@ -565,15 +557,6 @@ private static void testCodeLensFor(String value, String fileUri, String templat assertCodeLens(actual, expected); } - private static Template createTemplate(String value, String fileUri, String projectUri, String templateBaseDir, - QuteProjectRegistry projectRegistry) { - Template template = TemplateParser.parse(value, fileUri != null ? fileUri : FILE_URI); - template.setProjectUri(projectUri); - projectRegistry.getProject(new ProjectInfo(projectUri, templateBaseDir)); - template.setProjectRegistry(projectRegistry); - return template; - } - public static CodeLens cl(Range range, String title, String command) { return new CodeLens(range, new Command(title, command), null); } @@ -592,6 +575,42 @@ public static void assertCodeLens(List actual, CodeLens... e } } + // ------------------- InlayHint assert + + public static void testInlayHintFor(String value, InlayHint... expected) throws Exception { + testInlayHintFor(value, null, expected); + } + + public static void testInlayHintFor(String value, QuteInlayHintSettings inlayHintSettings, InlayHint... expected) + throws Exception { + testInlayHintFor(value, FILE_URI, null, PROJECT_URI, TEMPLATE_BASE_DIR, inlayHintSettings, expected); + } + + private static void testInlayHintFor(String value, String fileUri, String templateId, String projectUri, + String templateBaseDir, QuteInlayHintSettings inlayHintSettings, InlayHint... expected) throws Exception { + QuteProjectRegistry projectRegistry = new MockQuteProjectRegistry(); + Template template = createTemplate(value, fileUri, projectUri, templateBaseDir, projectRegistry); + template.setTemplateId(templateId); + + QuteLanguageService languageService = new QuteLanguageService(new JavaDataModelCache(projectRegistry)); + Range range = null; + List actual = languageService.getInlayHint(template, range, inlayHintSettings, () -> { + }).get(); + assertInlayHint(actual, expected); + } + + public static InlayHint ih(Position position, String label) { + return new InlayHint(position, Either.forLeft(label)); + } + + public static void assertInlayHint(List actual, InlayHint... expected) { + assertEquals(expected.length, actual.size()); + for (int i = 0; i < expected.length; i++) { + assertEquals(expected[i].getPosition(), actual.get(i).getPosition(), "position at " + i); + assertEquals(expected[i].getLabel(), actual.get(i).getLabel(), "label at " + i); + } + } + // ------------------- CodeAction assert public static void testCodeActionsFor(String value, Diagnostic diagnostic, CodeAction... expected) @@ -814,4 +833,30 @@ public static void assertDocumentSymbols(List actual, DocumentSy assertEquals(expected.length, actual.size()); assertArrayEquals(expected, actual.toArray()); } + + // ------------------- Utilities + + public static Range r(int line, int startChar, int endChar) { + return r(line, startChar, line, endChar); + } + + public static Range r(int startLine, int startChar, int endLine, int endChar) { + Position start = p(startLine, startChar); + Position end = p(endLine, endChar); + return new Range(start, end); + } + + public static Position p(int line, int character) { + return new Position(line, character); + } + + private static Template createTemplate(String value, String fileUri, String projectUri, String templateBaseDir, + QuteProjectRegistry projectRegistry) { + Template template = TemplateParser.parse(value, fileUri != null ? fileUri : FILE_URI); + template.setProjectUri(projectUri); + projectRegistry.getProject(new ProjectInfo(projectUri, templateBaseDir)); + template.setProjectRegistry(projectRegistry); + return template; + } + } diff --git a/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/services/QuteInlayHintTest.java b/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/services/QuteInlayHintTest.java new file mode 100644 index 000000000..28813d2f4 --- /dev/null +++ b/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/services/QuteInlayHintTest.java @@ -0,0 +1,98 @@ +/******************************************************************************* +* Copyright (c) 2022 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.services; + +import static com.redhat.qute.QuteAssert.ih; +import static com.redhat.qute.QuteAssert.p; +import static com.redhat.qute.QuteAssert.testInlayHintFor; + +import org.junit.jupiter.api.Test; + +import com.redhat.qute.settings.QuteInlayHintSettings; + +/** + * Tests for Qute inlay hint. + * + * @author Angelo ZERR + * + */ +public class QuteInlayHintTest { + + @Test + public void aliasForSection() throws Exception { + String template = "{@java.util.List items}\r\n" + // + "{#for item in items}\r\n" + // item[:Item] + " {item.name}\r\n" + // + "{/for}"; + testInlayHintFor(template, // + ih(p(1, 10), ":Item")); + + // enabled=false + QuteInlayHintSettings settings = new QuteInlayHintSettings(); + settings.setEnabled(false); + testInlayHintFor(template, // + settings); + + // showSectionParameterType=false + settings = new QuteInlayHintSettings(); + settings.setShowSectionParameterType(false); + testInlayHintFor(template, // + settings); + + } + + @Test + public void parameterLetSection() throws Exception { + String template = "{@org.acme.Item item}\r\n" + // + "{#let name=item.name price=item.price bad=item.XXXX}\r\n" + // name[:String]=item.name + // price[:BigInteger]=item.price + // bad=item.XXXX + " \r\n" + // + "{/let}"; + testInlayHintFor(template, // + ih(p(1, 10), ":String"), // + ih(p(1, 26), ":BigInteger")); + + // enabled=false + QuteInlayHintSettings settings = new QuteInlayHintSettings(); + settings.setEnabled(false); + testInlayHintFor(template, // + settings); + + // showSectionParameterType=false + settings = new QuteInlayHintSettings(); + settings.setShowSectionParameterType(false); + testInlayHintFor(template, // + settings); + } + + @Test + public void parameterMethod() throws Exception { + String template = "{@org.acme.Item item}\r\n" + // + "{item.name.substring(0, item.name.isEmpty)}"; // item.name.substring([:Integer]0, + // [:boolean]item.name.isEmpty) + testInlayHintFor(template, // + ih(p(1, 22), ":Integer"), ih(p(1, 41), ":boolean")); + + // enabled=false + QuteInlayHintSettings settings = new QuteInlayHintSettings(); + settings.setEnabled(false); + testInlayHintFor(template, // + settings); + + // showMethodParameterType=false + settings = new QuteInlayHintSettings(); + settings.setShowMethodParameterType(false); + testInlayHintFor(template, // + settings); + } +}