Preference pages for props and yaml ls editor

Allows configuring problem severities.
The ui works but is not yet wired to transmit
these setting to the language server.
This commit is contained in:
Kris De Volder
2020-10-02 10:22:41 -07:00
parent 0a29c539b5
commit dbe9520f3d
25 changed files with 632 additions and 64 deletions

View File

@@ -30,6 +30,7 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.springframework.ide.eclipse.boot.core.BootPropertyTester;
import org.springframework.ide.eclipse.boot.validation.BootValidationActivator;
import org.springframework.ide.eclipse.boot.validation.preferences.BootValidationPreferencesPage;
import org.springframework.ide.eclipse.boot.validation.rules.ValidationRuleDefinitions;
import org.springframework.ide.eclipse.editor.support.preferences.EditorType;
import org.springframework.ide.eclipse.editor.support.preferences.PreferencesBasedSeverityProvider;
@@ -111,7 +112,7 @@ public class SpringBootProjectBuilder extends IncrementalProjectBuilder {
}
private IValidationContext validationContext(IResource rsrc, IValidationRule rule) {
SeverityProvider severityProvider = new PreferencesBasedSeverityProvider(rsrc.getProject(), BootValidationActivator.PLUGIN_ID, EditorType.JAVA);
SeverityProvider severityProvider = new PreferencesBasedSeverityProvider(BootValidationPreferencesPage.util, rsrc.getProject(), BootValidationActivator.PLUGIN_ID, EditorType.JAVA);
return (IResource cu, ProblemType problemId, String msg, int offset, int end) -> {
ProblemSeverity severity = severityProvider.getSeverity(problemId);
if (severity==ProblemSeverity.IGNORE) {

View File

@@ -24,13 +24,20 @@ import org.springframework.ide.eclipse.editor.support.reconcile.ProblemType;
*/
public class BootValidationPreferencesPage extends AbstractProblemSeverityPreferencesPage {
public static final ProblemSeverityPreferencesUtil util = new ProblemSeverityPreferencesUtil("boot.project.validation.builder.");
public BootValidationPreferencesPage() {
super(util);
}
protected List<ProblemType> getProblemTypes() {
return BootValidationProblemType.values();
}
@Override
protected String getEnableProjectPreferencesKey() {
return ProblemSeverityPreferencesUtil.ENABLE_PROJECT_PREFERENCES(EditorType.PROP);
return util.ENABLE_PROJECT_PREFERENCES(EditorType.PROP);
}
@Override

View File

@@ -16,7 +16,6 @@ import org.springframework.ide.eclipse.boot.validation.BootValidationActivator;
import org.springframework.ide.eclipse.boot.validation.rules.ValidationRuleDefinitions;
import org.springframework.ide.eclipse.editor.support.preferences.AbstractProblemSeverityPreferencesPage;
import org.springframework.ide.eclipse.editor.support.preferences.EditorType;
import org.springframework.ide.eclipse.editor.support.preferences.ProblemSeverityPreferencesUtil;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemType;
/**
@@ -24,13 +23,17 @@ import org.springframework.ide.eclipse.editor.support.reconcile.ProblemType;
*/
public class BootValidationProjectPropertyPage extends AbstractProblemSeverityPreferencesPage {
public BootValidationProjectPropertyPage() {
super(BootValidationPreferencesPage.util);
}
protected List<ProblemType> getProblemTypes() {
return ValidationRuleDefinitions.getProblemTypes();
}
@Override
protected String getEnableProjectPreferencesKey() {
return ProblemSeverityPreferencesUtil.ENABLE_PROJECT_PREFERENCES(EditorType.JAVA);
return BootValidationPreferencesPage.util.ENABLE_PROJECT_PREFERENCES(EditorType.JAVA);
}
@Override

View File

@@ -25,7 +25,8 @@ Require-Bundle: org.eclipse.ui,
org.reactivestreams.reactive-streams;bundle-version="1.0.0",
org.apache.commons.lang3,
org.springsource.ide.eclipse.commons.ui,
javax.inject
javax.inject,
com.google.gson
Bundle-ActivationPolicy: lazy
Export-Package: org.springframework.ide.eclipse.editor.support,
org.springframework.ide.eclipse.editor.support.completions,

View File

@@ -54,6 +54,8 @@ import org.springsource.ide.eclipse.commons.livexp.core.UIValueListener;
*/
public abstract class AbstractProblemSeverityPreferencesPage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage, IWorkbenchPropertyPage {
private final ProblemSeverityPreferencesUtil util;
/**
* Project for a project propertypage, or null for a workspace preference page.
*/
@@ -64,6 +66,8 @@ public abstract class AbstractProblemSeverityPreferencesPage extends FieldEditor
*/
private LiveVariable<Boolean> enablePreferences = new LiveVariable<>(true);
private boolean initialized;
private static final Comparator<ProblemType> PROBLEM_TYPE_COMPARATOR = new Comparator<ProblemType>() {
public int compare(ProblemType o1, ProblemType o2) {
@@ -76,9 +80,9 @@ public abstract class AbstractProblemSeverityPreferencesPage extends FieldEditor
{"Ignore", ProblemSeverity.IGNORE.toString()}
};
protected AbstractProblemSeverityPreferencesPage() {
protected AbstractProblemSeverityPreferencesPage(ProblemSeverityPreferencesUtil util) {
super(FieldEditorPreferencePage.GRID);
initializeDefaults();
this.util = util;
}
/**
@@ -90,7 +94,7 @@ public abstract class AbstractProblemSeverityPreferencesPage extends FieldEditor
protected void initializeDefaults() {
IEclipsePreferences defaults = DefaultScope.INSTANCE.getNode(getPluginId());
for (ProblemType problemType : getProblemTypes()) {
defaults.put(getPreferenceName(problemType), problemType.getDefaultSeverity().toString());
defaults.put(util.getPreferenceName(problemType), problemType.getDefaultSeverity().toString());
}
try {
defaults.flush();
@@ -112,12 +116,16 @@ public abstract class AbstractProblemSeverityPreferencesPage extends FieldEditor
@Override
protected void createFieldEditors() {
if (!initialized) {
initialized = true;
initializeDefaults();
}
ProblemType[] problemTypes = getProblemTypes().toArray(new ProblemType[0]);
Arrays.sort(problemTypes, PROBLEM_TYPE_COMPARATOR);
for (ProblemType problemType : problemTypes) {
ComboFieldEditor field = new ComboFieldEditor(
ProblemSeverityPreferencesUtil.getPreferenceName(problemType),
util.getPreferenceName(problemType),
problemType.getLabel(),
SEVERITY_NAMES_AND_VALUES,
getFieldEditorParent()

View File

@@ -35,15 +35,18 @@ public class PreferencesBasedSeverityProvider implements SeverityProvider {
private IPreferenceStore workspacePrefs;
private Map<ProblemType, ProblemSeverity> cache = null;
private final ProblemSeverityPreferencesUtil util;
public PreferencesBasedSeverityProvider(IPreferenceStore projectPrefs, IPreferenceStore workspacePrefs, EditorType editorType) {
public PreferencesBasedSeverityProvider(ProblemSeverityPreferencesUtil util, IPreferenceStore projectPrefs, IPreferenceStore workspacePrefs, EditorType editorType) {
this.util = util;
this.projectPrefs = projectPrefs;
this.workspacePrefs = workspacePrefs;
this.editorType = editorType;
}
public PreferencesBasedSeverityProvider(IProject project, String pluginId, EditorType editorType) {
public PreferencesBasedSeverityProvider(ProblemSeverityPreferencesUtil util, IProject project, String pluginId, EditorType editorType) {
this(
util,
new ScopedPreferenceStore(new ProjectScope(project), pluginId),
new ScopedPreferenceStore(InstanceScope.INSTANCE, pluginId),
editorType
@@ -56,7 +59,7 @@ public class PreferencesBasedSeverityProvider implements SeverityProvider {
}
ProblemSeverity existing = cache.get(problemType);
if (existing==null) {
cache.put(problemType, existing = ProblemSeverityPreferencesUtil.getSeverity(getPrefs(), problemType));
cache.put(problemType, existing = util.getSeverity(getPrefs(), problemType));
}
return existing;
}
@@ -71,7 +74,7 @@ public class PreferencesBasedSeverityProvider implements SeverityProvider {
private boolean useProjectPreferences() {
if (projectPrefs!=null) {
return ProblemSeverityPreferencesUtil.projectPreferencesEnabled(projectPrefs, editorType);
return util.projectPreferencesEnabled(projectPrefs, editorType);
}
return false;
}

View File

@@ -24,17 +24,21 @@ import org.springsource.ide.eclipse.commons.core.util.StringUtil;
*/
public class ProblemSeverityPreferencesUtil {
public static final String PREFERENCE_PREFIX = "spring.properties.editor.problem.";
public final String PREFERENCE_PREFIX;// = "spring.properties.editor.problem.";
public static final String ENABLE_PROJECT_PREFERENCES(EditorType et) {
public ProblemSeverityPreferencesUtil(String preferencePrefix) {
this.PREFERENCE_PREFIX = preferencePrefix;
}
public final String ENABLE_PROJECT_PREFERENCES(EditorType et) {
return PREFERENCE_PREFIX+et+".project.prefs.enabled";
}
public static String getPreferenceName(ProblemType problemType) {
return PREFERENCE_PREFIX+problemType.toString();
public String getPreferenceName(ProblemType problemType) {
return PREFERENCE_PREFIX+problemType.getId();
}
public static ProblemSeverity getSeverity(IPreferenceStore prefs, ProblemType problemType) {
public ProblemSeverity getSeverity(IPreferenceStore prefs, ProblemType problemType) {
String value = prefs.getString(getPreferenceName(problemType));
try {
if (StringUtil.hasText(value)) {
@@ -47,15 +51,15 @@ public class ProblemSeverityPreferencesUtil {
return problemType.getDefaultSeverity();
}
public static void setSeverity(IPreferenceStore prefs, ProblemType problemType, ProblemSeverity severity) {
public void setSeverity(IPreferenceStore prefs, ProblemType problemType, ProblemSeverity severity) {
prefs.setValue(getPreferenceName(problemType), severity.toString());
}
public static boolean projectPreferencesEnabled(IPreferenceStore projectPrefs, EditorType et) {
public boolean projectPreferencesEnabled(IPreferenceStore projectPrefs, EditorType et) {
return projectPrefs.getBoolean(ENABLE_PROJECT_PREFERENCES(et));
}
public static void enableProjectPrefs(IPreferenceStore projectPrefs, EditorType et, boolean enable) {
public void enableProjectPrefs(IPreferenceStore projectPrefs, EditorType et, boolean enable) {
projectPrefs.setValue(ENABLE_PROJECT_PREFERENCES(et), enable);
}

View File

@@ -0,0 +1,99 @@
/*******************************************************************************
* 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.eclipse.editor.support.preferences;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemSeverity;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemType;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
public abstract class ProblemSeverityPreferityPageFromMetadata extends AbstractProblemSeverityPreferencesPage {
public static Map<String, ProblemTypeData[]> readFromFile(File metadataFile) throws FileNotFoundException, IOException {
Gson gson = new Gson();
TypeToken<Map<String, ProblemTypeData[]>> tt = new TypeToken<Map<String,ProblemTypeData[]>>() {};
try (Reader json = new FileReader(metadataFile)) {
return gson.fromJson(json, tt.getType());
}
}
public static class ProblemTypeData implements ProblemType {
String code;
String label;
String description;
String defaultSeverity;
public ProblemTypeData() {}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public ProblemSeverity getDefaultSeverity() {
return ProblemSeverity.valueOf(defaultSeverity);
}
public void setDefaultSeverity(String defaultSeverity) {
this.defaultSeverity = defaultSeverity;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
@Override
public String getId() {
return code;
}
}
private ProblemType[] problemTypes;
public ProblemSeverityPreferityPageFromMetadata(ProblemSeverityPreferencesUtil util, ProblemTypeData[] problemTypeJsonData) {
super(util);
this.problemTypes = problemTypeJsonData;
}
@Override
protected List<ProblemType> getProblemTypes() {
return Arrays.asList(problemTypes);
}
@Override
protected String getEnableProjectPreferencesKey() {
// TODO Auto-generated method stub
return null;
}
}

View File

@@ -5,4 +5,4 @@ cd ../headless-services
./mvnw clean install -Dmaven.test.skip=true
cd $workdir
./mvnw -Pe416 clean install -Dmaven.test.skip=true
./mvnw -Psnapshot -Pe416 clean install -Dmaven.test.skip=true

View File

@@ -31,7 +31,8 @@ Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0",
org.eclipse.mylyn.wikitext,
com.google.gson,
org.eclipse.lsp4e.jdt;bundle-version="0.10.0",
org.springsource.ide.eclipse.commons.boot.ls
org.springsource.ide.eclipse.commons.boot.ls,
org.springframework.ide.eclipse.editor.support
Import-Package: com.google.common.base,
com.google.common.collect,
com.google.gson;version="2.7.0",

View File

@@ -130,8 +130,22 @@
id="org.springframework.tooling.boot.ls.preferences"
name="Spring Boot Language Server">
</page>
<page
name="Properties Editor"
category="org.springframework.tooling.boot.ls.preferences"
class="org.springframework.tooling.boot.ls.prefs.ApplicationPropertiesEditorProblemSeverityPrefsPage"
id="org.springframework.tooling.boot.ls.prefs.ApplicationPropertiesEditorProblemSeverityPrefsPage">
</page>
<page
name="Yaml Editor"
category="org.springframework.tooling.boot.ls.preferences"
class="org.springframework.tooling.boot.ls.prefs.ApplicationYamlEditorProblemSeverityPrefsPage"
id="org.springframework.tooling.boot.ls.prefs.ApplicationYamlEditorProblemSeverityPrefsPage">
</page>
</extension>
<extension
point="org.eclipse.core.runtime.preferences">
<initializer

View File

@@ -0,0 +1,32 @@
/*******************************************************************************
* 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.tooling.boot.ls.prefs;
import java.io.IOException;
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 ApplicationPropertiesEditorProblemSeverityPrefsPage() throws IOException {
super(util, LanguageServerProblemTypesMetadata.load().get("application-properties"));
}
@Override
protected String getPluginId() {
return BootLanguageServerPlugin.PLUGIN_ID;
}
}

View File

@@ -0,0 +1,32 @@
/*******************************************************************************
* 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.tooling.boot.ls.prefs;
import java.io.IOException;
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 ApplicationYamlEditorProblemSeverityPrefsPage extends ProblemSeverityPreferityPageFromMetadata {
public static final ProblemSeverityPreferencesUtil util = new ProblemSeverityPreferencesUtil("application.yaml.problem.");
public ApplicationYamlEditorProblemSeverityPrefsPage() throws IOException {
super(util, LanguageServerProblemTypesMetadata.load().get("application-yaml"));
}
@Override
protected String getPluginId() {
return BootLanguageServerPlugin.PLUGIN_ID;
}
}

View File

@@ -0,0 +1,29 @@
/*******************************************************************************
* 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.tooling.boot.ls.prefs;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import org.eclipse.core.runtime.FileLocator;
import org.springframework.ide.eclipse.editor.support.preferences.ProblemSeverityPreferityPageFromMetadata.ProblemTypeData;
import org.springframework.tooling.boot.ls.BootLanguageServerPlugin;
public class LanguageServerProblemTypesMetadata {
public static Map<String, ProblemTypeData[]> load() throws IOException {
File root = FileLocator.getBundleFile(BootLanguageServerPlugin.getDefault().getBundle());
File metadataFile = root.toPath().resolve("servers/spring-boot-language-server/BOOT-INF/classes/problem-types.json").toFile();
return ApplicationPropertiesEditorProblemSeverityPrefsPage.readFromFile(metadataFile);
}
}

View File

@@ -38,10 +38,14 @@
</ciManagement>
<modules>
<module>../eclipse-extensions/org.springframework.ide.eclipse.boot</module>
<module>../eclipse-extensions/org.springframework.ide.eclipse.editor.support</module>
<module>../headless-services/jdt-ls-extension</module>
<module>org.springframework.tooling.ls.eclipse.commons</module>
<module>org.springframework.tooling.ls.eclipse.commons.test</module>
<module>org.springsource.ide.eclipse.commons.boot.ls</module>
<module>org.springsource.ide.eclipse.commons.core</module>
<module>org.springsource.ide.eclipse.commons.frameworks.core</module>
@@ -292,6 +296,11 @@
<layout>p2</layout>
<url>https://dist.springsource.com/release/TOOLS/third-party/misc-p2-repo/${misc.p2.repo.version}</url>
</repository>
<repository>
<id>yedit</id>
<layout>p2</layout>
<url>https://dist.springsource.com/release/TOOLS/third-party/yedit</url>
</repository>
</repositories>
<pluginRepositories>

View File

@@ -36,6 +36,16 @@ public class BadWordReconcileEngine implements IReconcileEngine {
public String getCode() {
return this.name();
}
@Override
public String getDescription() {
return "It is bad";
}
@Override
public String getLabel() {
return "Bad label";
}
}
private final String[] BADWORDS = {

View File

@@ -26,4 +26,6 @@ public interface ProblemType {
ProblemSeverity getDefaultSeverity();
String toString();
String getCode();
String getLabel();
String getDescription();
}

View File

@@ -10,18 +10,24 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver.reconcile;
public class ProblemTypes {
import java.util.HashSet;
import org.springframework.ide.vscode.commons.util.Assert;
public class ProblemTypes {
/**
* Creates a new problem type. The newly created problem type is not 'equals' to any other
* problem type.
*
* This method is deprecated. Look at ApplicationYamlProblemType for an example of how to define
* problem types to facilitate integration with preferences ui.
*
* @param defaultSeverity
* @param typeName A unique name for this problem type. Note that it is the caller's responsibility that the typeName is unique.
* If this method is called more than once with identical typeName's it makes no attempts to veify that
* the name is uniquer, or to return the same object for the same typeName.
* @return A newly create problem type.
*/
@Deprecated
public static ProblemType create(String typeName, ProblemSeverity defaultSeverity) {
return new ProblemType() {
@Override
@@ -36,6 +42,14 @@ public class ProblemTypes {
public String getCode() {
return typeName;
}
@Override
public String getDescription() {
return typeName;
}
@Override
public String getLabel() {
return typeName;
}
};
}

View File

@@ -57,7 +57,6 @@ public class SpelExpressionReconciler implements Reconciler {
private void createProblem(String spelExpression, String message, int startPosition, int position, IProblemCollector problemCollector) {
int start = startPosition + position;
int length = spelExpression.length() - position;
ReconcileProblem problem = new ReconcileProblemImpl(ProblemTypes.create("SpEL Expression Problem", ProblemSeverity.ERROR), message, start, length);
problemCollector.accept(problem);
}

View File

@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.properties.reconcile;
import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.ERROR;
import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.WARNING;
import org.springframework.boot.SpringApplication;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
@@ -20,7 +21,7 @@ import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemTy
* @author Kris De Volder
*/
public enum ApplicationPropertiesProblemType implements ProblemType {
PROP_INVALID_BEAN_NAVIGATION("Accessing a 'bean property' in a type that doesn't have properties (e.g. like String or Integer)"),
PROP_INVALID_INDEXED_NAVIGATION("Accessing a property using [] in a type that doesn't support that"),
PROP_EXPECTED_DOT_OR_LBRACK("Unexpected character found where a '.' or '[' was expected"),

View File

@@ -11,44 +11,12 @@
package org.springframework.ide.vscode.boot.yaml.reconcile;
import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.ERROR;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
public class ApplicationYamlProblems {
public static enum Type implements ProblemType {
YAML_SYNTAX_ERROR;
Type() {
this(ERROR);
}
Type(ProblemSeverity defaultSeverity) {
this.severity = defaultSeverity;
}
private final ProblemSeverity severity;
@Override
public ProblemSeverity getDefaultSeverity() {
return severity;
}
@Override
public String getCode() {
return name();
}
}
public static final String YAML_SYNTAX_ERROR = "YAML_SYNTAX_ERROR";
public static ReconcileProblem problem(Type type, String msg, int offset, int len) {
public static ReconcileProblem problem(ApplicationYamlProblemType type, String msg, int offset, int len) {
return new ReconcileProblemImpl(type, msg, offset, len);
}
}

View File

@@ -10,8 +10,6 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.yaml.reconcile;
import static org.springframework.ide.vscode.boot.yaml.reconcile.ApplicationYamlProblems.Type.YAML_SYNTAX_ERROR;
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
import org.springframework.ide.vscode.boot.metadata.IndexNavigator;
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
@@ -53,6 +51,6 @@ public class ApplicationYamlReconcileEngine extends YamlReconcileEngine {
@Override
protected ReconcileProblem syntaxError(String msg, int offset, int len) {
return ApplicationYamlProblems.problem(YAML_SYNTAX_ERROR, msg, offset, len);
return ApplicationYamlProblems.problem(ApplicationYamlProblemType.YAML_SYNTAX_ERROR, msg, offset, len);
}
}

View File

@@ -0,0 +1,150 @@
{
"application-yaml": [
{
"code": "YAML_SYNTAX_ERROR",
"label": "Syntax error",
"description": "Error parsing the input using snakeyaml",
"defaultSeverity": "ERROR"
},
{
"code": "YAML_UNKNOWN_PROPERTY",
"label": "Unknown property",
"description": "Property-key not found in the configuration metadata on the project\u0027s classpath",
"defaultSeverity": "WARNING"
},
{
"code": "YAML_VALUE_TYPE_MISMATCH",
"label": "Value type mismatch",
"description": "Expecting a value of a certain type, but value doesn\u0027t parse as such",
"defaultSeverity": "ERROR"
},
{
"code": "YAML_EXPECT_SCALAR",
"label": "Expect scalar",
"description": "Expecting a \u0027scalar\u0027 value but found something more complex.",
"defaultSeverity": "ERROR"
},
{
"code": "YAML_EXPECT_TYPE_FOUND_SEQUENCE",
"label": "Expect type found sequence",
"description": "Found a \u0027sequence\u0027 node where a non \u0027list-like\u0027 type is expected",
"defaultSeverity": "ERROR"
},
{
"code": "YAML_EXPECT_TYPE_FOUND_MAPPING",
"label": "Expect type found mapping",
"description": "Found a \u0027mapping\u0027 node where a type that can\u0027t be treated as a \u0027property map\u0027 is expected",
"defaultSeverity": "ERROR"
},
{
"code": "YAML_EXPECT_MAPPING",
"label": "Expect mapping",
"description": "Expecting a \u0027mapping\u0027 node but found something else",
"defaultSeverity": "ERROR"
},
{
"code": "YAML_EXPECT_BEAN_PROPERTY_NAME",
"label": "Expect bean property name",
"description": "Expecting a \u0027bean property\u0027 name but found something more complex",
"defaultSeverity": "ERROR"
},
{
"code": "YAML_INVALID_BEAN_PROPERTY",
"label": "Invalid bean property",
"description": "Accessing a named property in a type that doesn\u0027t provide a property accessor with that name",
"defaultSeverity": "ERROR"
},
{
"code": "YAML_DEPRECATED_ERROR",
"label": "Deprecated error",
"description": "Property is marked as Deprecated(Error)",
"defaultSeverity": "ERROR"
},
{
"code": "YAML_DEPRECATED_WARNING",
"label": "Deprecated warning",
"description": "Property is marked as Deprecated(Warning)",
"defaultSeverity": "WARNING"
},
{
"code": "YAML_DUPLICATE_KEY",
"label": "Duplicate key",
"description": "A mapping node contains multiple entries for the same key",
"defaultSeverity": "ERROR"
},
{
"code": "YAML_SHOULD_ESCAPE",
"label": "Should escape",
"description": "This key contains special characters and should probably be escaped by surrounding it with \u0027[]\u0027",
"defaultSeverity": "WARNING"
}
],
"application-properties": [
{
"code": "PROP_INVALID_BEAN_NAVIGATION",
"label": "Invalid bean navigation",
"description": "Accessing a \u0027bean property\u0027 in a type that doesn\u0027t have properties (e.g. like String or Integer)",
"defaultSeverity": "ERROR"
},
{
"code": "PROP_INVALID_INDEXED_NAVIGATION",
"label": "Invalid indexed navigation",
"description": "Accessing a property using [] in a type that doesn\u0027t support that",
"defaultSeverity": "ERROR"
},
{
"code": "PROP_EXPECTED_DOT_OR_LBRACK",
"label": "Expected dot or lbrack",
"description": "Unexpected character found where a \u0027.\u0027 or \u0027[\u0027 was expected",
"defaultSeverity": "ERROR"
},
{
"code": "PROP_NO_MATCHING_RBRACK",
"label": "No matching rbrack",
"description": "Found a \u0027[\u0027 but no matching \u0027]\u0027",
"defaultSeverity": "ERROR"
},
{
"code": "PROP_NON_INTEGER_IN_BRACKETS",
"label": "Non integer in brackets",
"description": "Use of [..] navigation with non-integer value",
"defaultSeverity": "ERROR"
},
{
"code": "PROP_VALUE_TYPE_MISMATCH",
"label": "Value type mismatch",
"description": "Expecting a value of a certain type, but value doesn\u0027t parse as such",
"defaultSeverity": "ERROR"
},
{
"code": "PROP_INVALID_BEAN_PROPERTY",
"label": "Invalid bean property",
"description": "Accessing a named property in a type that doesn\u0027t provide a property accessor with that name",
"defaultSeverity": "ERROR"
},
{
"code": "PROP_UNKNOWN_PROPERTY",
"label": "Unknown property",
"description": "Property-key not found in any configuration metadata on the project\u0027s classpath",
"defaultSeverity": "WARNING"
},
{
"code": "PROP_DEPRECATED",
"label": "Deprecated",
"description": "Property is marked as Deprecated",
"defaultSeverity": "WARNING"
},
{
"code": "PROP_DUPLICATE_KEY",
"label": "Duplicate key",
"description": "Multiple assignments to the same property value",
"defaultSeverity": "ERROR"
},
{
"code": "PROP_SYNTAX_ERROR",
"label": "Syntax error",
"description": "Syntax Error",
"defaultSeverity": "ERROR"
}
]
}

View File

@@ -0,0 +1,29 @@
/*******************************************************************************
* 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.test;
import org.junit.jupiter.api.Test;
import org.springframework.ide.vscode.boot.properties.reconcile.ApplicationPropertiesProblemType;
import org.springframework.ide.vscode.boot.yaml.reconcile.ApplicationYamlProblemType;
public class ProblemTypesMetadataTest {
@Test
public void dataIsConsitent() throws Exception {
//If this test fails it probably just means you have to run the main
// method in org.springframework.ide.vscode.boot.test.ProblemTypesToJson
// to synchronize the metadata json file with the real problem type objects in the source code.
ProblemTypesToJson reader = new ProblemTypesToJson().read();
reader.validate("application-properties", ApplicationPropertiesProblemType.values());
reader.validate("application-yaml", ApplicationYamlProblemType.values());
}
}

View File

@@ -0,0 +1,154 @@
/*******************************************************************************
* 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.test;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.io.FileUtils;
import org.springframework.ide.vscode.boot.properties.reconcile.ApplicationPropertiesProblemType;
import org.springframework.ide.vscode.boot.yaml.reconcile.ApplicationYamlProblemType;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
/**
* Helper that dumps out ProblemTypes to a json file. This file can
* be used (how?) to drive problem severity configuration ui.
* <p>
* Run this from Eclipse simply by selecting this file and do
* "Run As >> Java Application"
*/
public class ProblemTypesToJson {
public static final String resourcesPath = "src/main/resources";
public static final String metaDataFileName = "problem-types.json";
public static class ProblemTypeData {
String code;
String label;
String description;
String defaultSeverity;
public ProblemTypeData() {}
public ProblemTypeData(ProblemType type) {
this.code = type.getCode();
this.description = type.getDescription();
this.defaultSeverity =type.getDefaultSeverity().toString();
this.label = type.getLabel();
}
public ProblemTypeData(String defaultSeverity) {
super();
this.setDefaultSeverity(defaultSeverity);
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getDefaultSeverity() {
return defaultSeverity;
}
public void setDefaultSeverity(String defaultSeverity) {
this.defaultSeverity = defaultSeverity;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
}
Map<String, ProblemTypeData[]> problemTypes = new HashMap<>();
public static void main(String[] args) throws IOException {
ProblemTypesToJson writer = new ProblemTypesToJson();
writer.problemsFor("application-yaml", ApplicationYamlProblemType.values());
writer.problemsFor("application-properties", ApplicationPropertiesProblemType.values());
writer.dump();
}
private void dump() throws IOException {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(problemTypes);
FileUtils.writeStringToFile(new File(resourcesPath+"/"+metaDataFileName), json);
}
private void problemsFor(String string, ProblemType[] values) {
ProblemTypeData[] data = new ProblemTypeData[values.length];
for (int i = 0; i < data.length; i++) {
data[i] = new ProblemTypeData(values[i]);
}
problemTypes.put(string, data);
}
public ProblemTypesToJson read() throws IOException {
try (InputStream input = this.getClass().getResourceAsStream("/"+metaDataFileName)) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
TypeToken<Map<String, ProblemTypeData[]>> tt = new TypeToken<Map<String, ProblemTypeData[]>>() {};
problemTypes = gson.fromJson(new InputStreamReader(input), tt.getType());
}
return this;
}
public void validate(String name, ProblemType[] actualProblemTypes) {
ProblemTypeData[] metadataProblemTypes = problemTypes.get(name);
Set<String> metadataHas = Stream.of(metadataProblemTypes).map(x -> x.getCode()).collect(Collectors.toSet());
Set<String> actualHas = Stream.of(actualProblemTypes).map(x-> x.getCode()).collect(Collectors.toSet());
for (String string : actualHas) {
if (!metadataHas.contains(string)) {
throw new IllegalStateException("No metadata for "+string);
}
}
for (String string : metadataHas) {
if (!actualHas.contains(string)) {
throw new IllegalStateException("Metadata for non-existent problem type "+string);
}
}
for (int i = 0; i < metadataProblemTypes.length; i++) {
ProblemTypeData metadata = metadataProblemTypes[i];
ProblemType actual = actualProblemTypes[i];
assertEquals(actual.getCode(), metadata.getCode());
assertEquals(actual.getDescription(), metadata.getDescription());
assertEquals(actual.getDefaultSeverity().toString(), metadata.getDefaultSeverity());
assertEquals(actual.getLabel(), metadata.getLabel());
}
}
}