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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user