Boot Language Server obeys configured problem severities

This commit is contained in:
Kris De Volder
2020-10-02 17:45:36 -07:00
parent dbe9520f3d
commit cd0eebcc15
12 changed files with 166 additions and 13 deletions

View File

@@ -12,6 +12,7 @@ package org.springframework.ide.eclipse.boot.validation.preferences;
import java.util.List;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.springframework.ide.eclipse.boot.validation.BootValidationActivator;
import org.springframework.ide.eclipse.boot.validation.rules.BootValidationProblemType;
import org.springframework.ide.eclipse.editor.support.preferences.AbstractProblemSeverityPreferencesPage;
@@ -45,4 +46,5 @@ public class BootValidationPreferencesPage extends AbstractProblemSeverityPrefer
return BootValidationActivator.PLUGIN_ID;
}
}

View File

@@ -19,11 +19,13 @@ import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.dialogs.ControlEnableState;
import org.eclipse.jface.preference.ComboFieldEditor;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
@@ -33,6 +35,7 @@ import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.IWorkbenchPropertyPage;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
import org.osgi.service.prefs.BackingStoreException;
import org.springframework.ide.eclipse.boot.util.Log;

View File

@@ -30,7 +30,7 @@ import org.osgi.framework.BundleContext;
*/
public class BootLanguageServerPlugin extends AbstractUIPlugin {
public static final String PLUGIN_ID = "org.springframework.tooling.boot.java.ls";
public static String PLUGIN_ID = "org.springframework.tooling.boot.ls";
private static final Object LSP4E_COMMAND_SYMBOL_IN_WORKSPACE = "org.eclipse.lsp4e.symbolinworkspace";

View File

@@ -23,6 +23,7 @@ import java.util.Map;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.lsp4e.server.StreamConnectionProvider;
@@ -35,6 +36,7 @@ import org.springframework.tooling.ls.eclipse.commons.LanguageServerCommonsActiv
import org.springsource.ide.eclipse.commons.boot.ls.remoteapps.RemoteBootAppsDataHolder;
import org.springsource.ide.eclipse.commons.boot.ls.remoteapps.RemoteBootAppsDataHolder.RemoteAppData;
import org.springsource.ide.eclipse.commons.livexp.core.ValueListener;
import org.springsource.ide.eclipse.commons.livexp.util.Log;
import com.google.common.collect.ImmutableSet;
@@ -64,6 +66,7 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
private LanguageServer languageServer;
private final IPropertyChangeListener configListener = (e) -> sendConfiguration();
private final ValueListener<ImmutableSet<RemoteAppData>> remoteAppsListener = (e, v) -> sendConfiguration();
private long timestampBeforeStart;
@@ -117,6 +120,7 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
fResourceListener = null;
}
BootLanguageServerPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(configListener);
// BootLanguageServerPlugin.getPreferences().removePreferenceChangeListener(prefsListener);
RemoteBootAppsDataHolder.getDefault().getRemoteApps().removeListener(remoteAppsListener);
}
@@ -134,6 +138,7 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
// Add config listener
BootLanguageServerPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(configListener);
// BootLanguageServerPlugin.getPreferences().addPreferenceChangeListener(prefsListener);
// Add resource listener
ResourcesPlugin.getWorkspace().addResourceChangeListener(fResourceListener = new ResourceListener(languageServer, Arrays.asList(
@@ -194,9 +199,46 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
bootJavaObj.put("validation", validation);
bootJavaObj.put("remote-apps", getAllRemoteApps());
settings.put("boot-java", bootJavaObj);
putValidationPreferences(settings);
this.languageServer.getWorkspaceService().didChangeConfiguration(new DidChangeConfigurationParams(settings));
}
private void putValidationPreferences(Map<String, Object> settings) {
try {
IEclipsePreferences prefs = BootLanguageServerPlugin.getPreferences();
for (String key : prefs.keys()) {
if (key.startsWith("problem.")) {
String val = prefs.get(key, null);
if (val!=null) {
dotPut(settings, "spring-boot.ls."+key, val);
}
}
}
} catch (Exception e) {
Log.log(e);
}
}
private void dotPut(Object _settings, String dottedProperty, Object value) {
if (_settings instanceof Map) {
Map<String, Object> settings = (Map<String, Object>) _settings;
int dot = dottedProperty.indexOf('.');
if (dot>=0) {
String first = dottedProperty.substring(0, dot);
String rest = dottedProperty.substring(dot+1);
Object nested = settings.getOrDefault(first, null);
if (nested==null) {
nested = new HashMap<>();
settings.put(first, nested);
}
dotPut(nested, rest, value);
} else {
settings.put(dottedProperty, value);
}
}
}
/**
* Combines remote boot app data from all configuration sources.

View File

@@ -12,13 +12,14 @@ package org.springframework.tooling.boot.ls.prefs;
import java.io.IOException;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.springframework.ide.eclipse.editor.support.preferences.ProblemSeverityPreferencesUtil;
import org.springframework.ide.eclipse.editor.support.preferences.ProblemSeverityPreferityPageFromMetadata;
import org.springframework.tooling.boot.ls.BootLanguageServerPlugin;
public class ApplicationPropertiesEditorProblemSeverityPrefsPage extends ProblemSeverityPreferityPageFromMetadata {
public static final ProblemSeverityPreferencesUtil util = new ProblemSeverityPreferencesUtil("application.properties.problem.");
public static final ProblemSeverityPreferencesUtil util = new ProblemSeverityPreferencesUtil("problem.properties.");
public ApplicationPropertiesEditorProblemSeverityPrefsPage() throws IOException {
super(util, LanguageServerProblemTypesMetadata.load().get("application-properties"));

View File

@@ -18,7 +18,7 @@ import org.springframework.tooling.boot.ls.BootLanguageServerPlugin;
public class ApplicationYamlEditorProblemSeverityPrefsPage extends ProblemSeverityPreferityPageFromMetadata {
public static final ProblemSeverityPreferencesUtil util = new ProblemSeverityPreferencesUtil("application.yaml.problem.");
public static final ProblemSeverityPreferencesUtil util = new ProblemSeverityPreferencesUtil("problem.yaml.");
public ApplicationYamlEditorProblemSeverityPrefsPage() throws IOException {
super(util, LanguageServerProblemTypesMetadata.load().get("application-yaml"));
@@ -28,5 +28,4 @@ public class ApplicationYamlEditorProblemSeverityPrefsPage extends ProblemSeveri
protected String getPluginId() {
return BootLanguageServerPlugin.PLUGIN_ID;
}
}

View File

@@ -14,10 +14,8 @@ import org.eclipse.lsp4j.DiagnosticSeverity;
@FunctionalInterface
public interface DiagnosticSeverityProvider {
DiagnosticSeverity getDiagnosticSeverity(ReconcileProblem problem);
static final DiagnosticSeverityProvider DEFAULT = (problem) -> {
ProblemSeverity severity = problem.getType().getDefaultSeverity();
static DiagnosticSeverity diagnosticSeverity(ProblemSeverity severity) {
switch (severity) {
case ERROR:
return DiagnosticSeverity.Error;
@@ -32,5 +30,12 @@ public interface DiagnosticSeverityProvider {
default:
throw new IllegalStateException("Bug! Missing switch case?");
}
}
DiagnosticSeverity getDiagnosticSeverity(ReconcileProblem problem);
static final DiagnosticSeverityProvider DEFAULT = (problem) -> {
ProblemSeverity severity = problem.getType().getDefaultSeverity();
return diagnosticSeverity(severity);
};
}

View File

@@ -93,4 +93,8 @@ public class ReconcileProblemImpl implements ReconcileProblem {
return this;
}
@Override
public String toString() {
return this.getClass().getSimpleName()+"("+type+", "+msg+")";
}
}

View File

@@ -15,10 +15,12 @@ import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
/**
@@ -129,7 +131,38 @@ public class Settings {
@Override
public String toString() {
return settings.toString();
return ""+settings;
}
public Settings navigate(String... names) {
if (this.settings!=null && !this.settings.isJsonNull()) {
if (names.length==0) {
return this;
} else if (this.settings.isJsonObject()) {
JsonObject obj = (JsonObject) this.settings;
if (obj.has(names[0])) {
Settings sub = new Settings(obj.get(names[0]));
return sub.navigate(cdr(names));
}
}
}
return new Settings(JsonNull.INSTANCE);
}
private String[] cdr(String[] names) {
String[] rest = new String[names.length-1];
for (int i = 0; i < rest.length; i++) {
rest[i] = names[i+1];
}
return rest;
}
public Iterable<String> keys() {
if (settings!=null && settings.isJsonObject()) {
JsonObject obj = (JsonObject) settings;
return obj.keySet();
}
return ImmutableList.of();
}
}

View File

@@ -39,9 +39,6 @@ public class BootJavaConfig implements InitializingBean {
public static final boolean VALIDAITON_SPEL_EXPRESSIONS_ENABLED_DEFAULT = true;
//TODO: Consider changing this to something that raises Spring application events.
// I.e. like described in here: https://www.baeldung.com/spring-events
private final SimpleWorkspaceService workspace;
private Settings settings = new Settings(null);
private ListenerList<Void> listeners = new ListenerList<Void>();
@@ -140,4 +137,8 @@ public class BootJavaConfig implements InitializingBean {
public void afterPropertiesSet() throws Exception {
workspace.onDidChangeConfiguraton(this::handleConfigurationChange);
}
public Settings getRawSettings() {
return settings;
}
}

View File

@@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright (c) 2020 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.app;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ide.vscode.commons.languageserver.reconcile.DiagnosticSeverityProvider;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
import org.springframework.ide.vscode.commons.languageserver.util.Settings;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.stereotype.Component;
@Component
public class ProblemSeverityConfigurer implements InitializingBean {
@Autowired
private SimpleLanguageServer server;
@Autowired
private BootJavaConfig config;
@Override
public void afterPropertiesSet() throws Exception {
config.addListener((x) -> configChanged());
configChanged();
}
private void configChanged() {
Settings settings = config.getRawSettings();
settings = settings.navigate("spring-boot", "ls", "problem");
Map<String, ProblemSeverity> severityOverrides = new HashMap<>();
for (String editorType : settings.keys()) {
Settings problemConf = settings.navigate(editorType);
for (String code : problemConf.keys()) {
String severity = problemConf.getString(code);
System.out.println(code+" => "+severity);
Assert.isLegal(!severityOverrides.containsKey(code), "Multpile entries for problem type "+code);
severityOverrides.put(code, ProblemSeverity.valueOf(severity));
}
}
server.setDiagnosticSeverityProvider((ReconcileProblem problem) -> {
ProblemSeverity severity = severityOverrides.get(problem.getType().getCode());
if (severity==null) {
severity = problem.getType().getDefaultSeverity();
}
return DiagnosticSeverityProvider.diagnosticSeverity(severity);
});
}
}

View File

@@ -45,5 +45,5 @@ public class SpringPropertyProblem extends ReconcileProblemImpl {
public void setPropertyName(String name) {
propertyName = name;
}
}