Skip to content

Commit

Permalink
feat: expose Qute server settings
Browse files Browse the repository at this point in the history
Signed-off-by: Fred Bricon <[email protected]>
  • Loading branch information
fbricon committed Aug 28, 2023
1 parent d379c70 commit d8e0c7d
Show file tree
Hide file tree
Showing 16 changed files with 487 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
public class MicroProfileInspectionsInfo {

//See https://github.com/eclipse/lsp4mp/blob/6b483c4d292bfebabd13311d6217291da2d5d169/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/settings/MicroProfileValidationSettings.java#L36
private boolean enabled = true;
private ProblemSeverity syntaxSeverity = ProblemSeverity.error;
private ProblemSeverity unknownSeverity = ProblemSeverity.warning;
private ProblemSeverity duplicateSeverity = ProblemSeverity.warning;
Expand All @@ -45,30 +44,17 @@ private MicroProfileInspectionsInfo() {
public static MicroProfileInspectionsInfo getMicroProfileInspectionInfo(Project project) {
MicroProfileInspectionsInfo wrapper = new MicroProfileInspectionsInfo();
InspectionProfile profile = InspectionProfileManager.getInstance(project).getCurrentProfile();
boolean syntaxEnabled = isInspectionEnabled(MicroProfilePropertiesSyntaxInspection.ID, profile);
boolean unknownEnabled = isInspectionEnabled(MicroProfilePropertiesUnknownInspection.ID, profile);
boolean duplicatedEnabled = isInspectionEnabled(MicroProfilePropertiesDuplicatesInspection.ID, profile);
boolean valueEnabled = isInspectionEnabled(MicroProfilePropertiesValueInspection.ID, profile);
boolean requiredEnabled = isInspectionEnabled(MicroProfilePropertiesRequiredInspection.ID, profile);
boolean expressionsEnabled = isInspectionEnabled(MicroProfilePropertiesExpressionsInspection.ID, profile);
wrapper.enabled = syntaxEnabled
|| unknownEnabled
|| duplicatedEnabled
|| valueEnabled
|| requiredEnabled
|| expressionsEnabled;

wrapper.syntaxSeverity = getSeverity(syntaxEnabled, MicroProfilePropertiesSyntaxInspection.ID, profile);
wrapper.unknownSeverity = getSeverity(unknownEnabled, MicroProfilePropertiesUnknownInspection.ID, profile);
wrapper.duplicateSeverity = getSeverity(duplicatedEnabled, MicroProfilePropertiesDuplicatesInspection.ID, profile);
wrapper.valueSeverity = getSeverity(valueEnabled, MicroProfilePropertiesValueInspection.ID, profile);
wrapper.requiredSeverity = getSeverity(requiredEnabled, MicroProfilePropertiesRequiredInspection.ID, profile);
wrapper.expressionSeverity = getSeverity(expressionsEnabled, MicroProfilePropertiesExpressionsInspection.ID, profile);
wrapper.syntaxSeverity = getSeverity(MicroProfilePropertiesSyntaxInspection.ID, profile);
wrapper.unknownSeverity = getSeverity(MicroProfilePropertiesUnknownInspection.ID, profile);
wrapper.duplicateSeverity = getSeverity(MicroProfilePropertiesDuplicatesInspection.ID, profile);
wrapper.valueSeverity = getSeverity(MicroProfilePropertiesValueInspection.ID, profile);
wrapper.requiredSeverity = getSeverity(MicroProfilePropertiesRequiredInspection.ID, profile);
wrapper.expressionSeverity = getSeverity(MicroProfilePropertiesExpressionsInspection.ID, profile);
return wrapper;
}

private static ProblemSeverity getSeverity(boolean enabled, String inspectionId, InspectionProfile profile) {
if (!enabled) {
private static ProblemSeverity getSeverity(String inspectionId, InspectionProfile profile) {
if (!isInspectionEnabled(inspectionId, profile)) {
return ProblemSeverity.none;
}
return ProblemSeverity.getSeverity(getErrorLevel(inspectionId, profile));
Expand All @@ -84,10 +70,6 @@ private static boolean isInspectionEnabled(@NotNull String inspectionId, @NotNul
return profile.isToolEnabled(HighlightDisplayKey.find(inspectionId));
}

public boolean enabled() {
return enabled;
}

public ProblemSeverity unknownSeverity() {
return unknownSeverity;
}
Expand Down Expand Up @@ -117,15 +99,14 @@ public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MicroProfileInspectionsInfo that = (MicroProfileInspectionsInfo) o;
return enabled == that.enabled
&& syntaxSeverity == that.syntaxSeverity && unknownSeverity == that.unknownSeverity
return syntaxSeverity == that.syntaxSeverity && unknownSeverity == that.unknownSeverity
&& duplicateSeverity == that.duplicateSeverity && valueSeverity == that.valueSeverity
&& requiredSeverity == that.requiredSeverity && expressionSeverity == that.expressionSeverity;
}

@Override
public int hashCode() {
return Objects.hash(enabled, syntaxSeverity, unknownSeverity, duplicateSeverity, valueSeverity, requiredSeverity,
return Objects.hash(syntaxSeverity, unknownSeverity, duplicateSeverity, valueSeverity, requiredSeverity,
expressionSeverity);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ public class UserDefinedMicroProfileSettings implements PersistentStateComponent

private volatile MyState myState = new MyState();

private final Project project;

public UserDefinedMicroProfileSettings(Project project) {
this.project = project;
}

private final List<Runnable> myChangeHandlers = ContainerUtil.createConcurrentList();

public static @NotNull UserDefinedMicroProfileSettings getInstance(@NotNull Project project) {
Expand All @@ -63,6 +69,13 @@ public void fireStateChanged() {
handler.run();
}
}
public boolean isValidationEnabled() {
return myState.myValidationEnabled;
}

public void setValidationEnabled(boolean validationEnabled) {
myState.myValidationEnabled = validationEnabled;
}

// ---------- Properties

Expand Down Expand Up @@ -103,8 +116,8 @@ public void loadState(@NotNull MyState state) {
*
* @return the proper settings expected by the MicroProfile language server.
*/
public Map<String, Object> toSettingsForMicroProfileLS(MicroProfileInspectionsInfo inspectionsInfo) {

public Map<String, Object> toSettingsForMicroProfileLS() {
MicroProfileInspectionsInfo inspectionsInfo = MicroProfileInspectionsInfo.getMicroProfileInspectionInfo(project);
Map<String, Object> settings = new HashMap<>();
Map<String, Object> microprofile = new HashMap<>();
settings.put("microprofile", microprofile);
Expand All @@ -125,7 +138,7 @@ public Map<String, Object> toSettingsForMicroProfileLS(MicroProfileInspectionsIn

Map<String, Object> validation = new HashMap<>();
tools.put("validation", validation);
validation.put("enabled", inspectionsInfo.enabled());
validation.put("enabled", isValidationEnabled());
validation.put("syntax", getSeverityNode(inspectionsInfo.syntaxSeverity()));
validation.put("unknown", getSeverityNode(inspectionsInfo.unknownSeverity()));
validation.put("duplicate", getSeverityNode(inspectionsInfo.duplicateSeverity()));
Expand All @@ -141,6 +154,10 @@ private Map<String, String> getSeverityNode(ProblemSeverity severity) {


public static class MyState {

@Tag("validationEnabled")
public boolean myValidationEnabled = true;

@Tag("inlayHintEnabled")
public boolean myInlayHintEnabled = true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public void dispose() {

@Override
protected Object createSettings() {
return UserDefinedMicroProfileSettings.getInstance(getProject()).toSettingsForMicroProfileLS(inspectionsInfo);
return UserDefinedMicroProfileSettings.getInstance(getProject()).toSettingsForMicroProfileLS();
}

private void sendPropertiesChangeEvent(List<MicroProfilePropertiesScope> scope, Set<String> uris) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ public QuarkusServer(Project project) {
@Override
public Object getInitializationOptions(URI rootUri) {
Map<String, Object> root = new HashMap<>();
MicroProfileInspectionsInfo inspectionsInfo = MicroProfileInspectionsInfo.getMicroProfileInspectionInfo(project);
Map<String, Object> settings = UserDefinedMicroProfileSettings.getInstance(project).toSettingsForMicroProfileLS(inspectionsInfo);
Map<String, Object> settings = UserDefinedMicroProfileSettings.getInstance(project).toSettingsForMicroProfileLS();
root.put("settings", settings);

Map<String, Object> extendedClientCapabilities = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,28 @@
******************************************************************************/
package com.redhat.devtools.intellij.qute.lsp;

import com.intellij.codeInspection.InspectionProfile;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.profile.ProfileChangeAdapter;
import com.intellij.util.messages.MessageBusConnection;
import com.redhat.devtools.intellij.lsp4ij.client.CoalesceByKey;
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.project.PsiMicroProfileProjectManager;
import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.core.ls.PsiUtilsLSImpl;
import com.redhat.devtools.intellij.lsp4ij.client.IndexAwareLanguageClient;
import com.redhat.devtools.intellij.lsp4mp4ij.classpath.ClasspathResourceChangedManager;
import com.redhat.devtools.intellij.lsp4mp4ij.settings.UserDefinedMicroProfileSettings;
import com.redhat.devtools.intellij.qute.psi.QuteSupportForJava;
import com.redhat.devtools.intellij.qute.psi.QuteSupportForTemplate;
import com.redhat.devtools.intellij.qute.psi.utils.PsiQuteProjectUtils;
import com.redhat.devtools.intellij.qute.settings.QuteInspectionsInfo;
import com.redhat.devtools.intellij.qute.settings.UserDefinedQuteSettings;
import com.redhat.qute.commons.GenerateMissingJavaMemberParams;
import com.redhat.qute.commons.JavaTypeInfo;
import com.redhat.qute.commons.ProjectInfo;
Expand All @@ -49,25 +58,31 @@
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
* Qute language client.
*/
public class QuteLanguageClient extends IndexAwareLanguageClient implements QuteLanguageClientAPI, ClasspathResourceChangedManager.Listener {
public class QuteLanguageClient extends IndexAwareLanguageClient implements QuteLanguageClientAPI, ClasspathResourceChangedManager.Listener, ProfileChangeAdapter {
private final MessageBusConnection connection;

private QuteInspectionsInfo inspectionsInfo;

public QuteLanguageClient(Project project) {
super(project);
connection = project.getMessageBus().connect(project);
connection.subscribe(ClasspathResourceChangedManager.TOPIC, this);
inspectionsInfo = QuteInspectionsInfo.getQuteInspectionsInfo(project);
connection.subscribe(ProfileChangeAdapter.TOPIC, this);
}

@Override
Expand All @@ -91,6 +106,28 @@ private void notifyQuteDataModelChanged(Set<String> uris) {
}
}

@Override
protected Object createSettings() {
return UserDefinedQuteSettings.getInstance(getProject()).toSettingsForQuteLS();
}

@Override
public void profileChanged(@NotNull InspectionProfile profile) {
// Track Qute inspections settings (declared in Editor/Inspection/Qute UI settings) changed,
// convert them to matching Qute configuration and push them via 'workspace/didChangeConfiguration'.
QuteInspectionsInfo newInspectionState = QuteInspectionsInfo.getQuteInspectionsInfo(getProject());
if (!Objects.equals(newInspectionState, inspectionsInfo)) {
inspectionsInfo = newInspectionState;
ApplicationManager.getApplication().invokeLater(() -> {
new Task.Backgroundable(getProject(), "Updating Qute LS configuration...", true) {
@Override
public void run(@NotNull ProgressIndicator progressIndicator) {
triggerChangeConfiguration();
}
}.queue();
}, ModalityState.defaultModalityState(), getProject().getDisposed());
}
}
@Override
public void librariesChanged() {
if (isDisposed()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
import com.intellij.ide.plugins.PluginManager;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.project.Project;
import com.redhat.devtools.intellij.lsp4mp4ij.settings.UserDefinedMicroProfileSettings;
import com.redhat.devtools.intellij.quarkus.TelemetryService;
import com.redhat.devtools.intellij.lsp4ij.server.JavaProcessCommandBuilder;
import com.redhat.devtools.intellij.lsp4ij.server.ProcessStreamConnectionProvider;
import com.redhat.devtools.intellij.qute.settings.QuteInspectionsInfo;
import com.redhat.devtools.intellij.qute.settings.UserDefinedQuteSettings;

import java.io.File;
import java.net.URI;
Expand All @@ -30,7 +33,10 @@
*/
public class QuteServer extends ProcessStreamConnectionProvider {

private final Project project;

public QuteServer(Project project) {
this.project = project;
IdeaPluginDescriptor descriptor = PluginManager.getPlugin(PluginId.getId("com.redhat.devtools.intellij.quarkus"));
File quteServerPath = new File(descriptor.getPath(), "lib/server/com.redhat.qute.ls-uber.jar");

Expand All @@ -46,7 +52,7 @@ public QuteServer(Project project) {
@Override
public Object getInitializationOptions(URI rootUri) {
Map<String, Object> root = new HashMap<>();
Map<String, Object> settings = QuteUtils.getQuteSettings();
Map<String, Object> settings = UserDefinedQuteSettings.getInstance(project).toSettingsForQuteLS();
Map<String, Object> extendedClientCapabilities = new HashMap<>();
Map<String, Object> commands = new HashMap<>();
Map<String, Object> commandsKind = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.devtools.intellij.qute.psi.core.inspections;

import com.intellij.codeInspection.LocalInspectionTool;

/**
* No-op {@link LocalInspectionTool} used as a basis for mapping inspection severities to matching LSP severities.
*/
public abstract class AbstractDelegateInspection extends LocalInspectionTool {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.devtools.intellij.qute.psi.core.inspections;

/**
* Dummy inspection for undefined namespaces in Qute templates
*/
public class QuteUndefinedNamespaceInspection extends AbstractDelegateInspection {
public static final String ID = getShortName(QuteUndefinedNamespaceInspection.class.getSimpleName());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.devtools.intellij.qute.psi.core.inspections;

/**
* Dummy inspection for undefined objects in Qute templates
*/
public class QuteUndefinedObjectInspection extends AbstractDelegateInspection {
public static final String ID = getShortName(QuteUndefinedObjectInspection.class.getSimpleName());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.devtools.intellij.qute.settings;

import com.intellij.lang.annotation.HighlightSeverity;
import org.jetbrains.annotations.NotNull;

/**
* Problem severity levels used by Qute LS
*/
//TODO move to lsp4ij?
public enum ProblemSeverity {
none, warning, error;

/**
* Maps {@link HighlightSeverity} to {@link ProblemSeverity} levels used by LSP4MP.
* <ul>
* <li>Any severity below <code>HighlightSeverity.WEAK_WARNING</code> is mapped to <code>ProblemSeverity.none</code></li>
* <li>Any severity below <code>HighlightSeverity.ERROR</code> is mapped to <code>ProblemSeverity.warning</code></li>
* <li>Any other severity is mapped to <code>ProblemSeverity.error</code></li>
* </ul>
*
* @param highlightSeverity the severity to map to a {@link ProblemSeverity}
* @return the matching {@link ProblemSeverity}
*/
public static @NotNull ProblemSeverity getSeverity(@NotNull HighlightSeverity highlightSeverity) {
if (HighlightSeverity.WEAK_WARNING.compareTo(highlightSeverity) > 0) {
return none;
}
if (HighlightSeverity.ERROR.compareTo(highlightSeverity) > 0) {
return warning;
}
return error;
}
}
Loading

0 comments on commit d8e0c7d

Please sign in to comment.