Categorize boot problems. Boot 3 reconciling.
This commit is contained in:
@@ -32,7 +32,8 @@ Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0",
|
||||
com.google.gson,
|
||||
org.eclipse.lsp4e.jdt;bundle-version="0.10.0",
|
||||
org.springsource.ide.eclipse.commons.boot.ls,
|
||||
org.springframework.ide.eclipse.editor.support
|
||||
org.springframework.ide.eclipse.editor.support,
|
||||
com.google.guava
|
||||
Import-Package: com.google.common.base,
|
||||
com.google.common.collect,
|
||||
com.google.gson;version="2.7.0",
|
||||
|
||||
@@ -132,24 +132,6 @@
|
||||
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>
|
||||
<page
|
||||
name="Java Editor"
|
||||
category="org.springframework.tooling.boot.ls.preferences"
|
||||
class="org.springframework.tooling.boot.ls.prefs.SpringJavaProblemSeverityPrefsPage"
|
||||
id="org.springframework.tooling.boot.ls.prefs.SpringJavaProblemSeverityPrefsPage">
|
||||
</page>
|
||||
</extension>
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.keys.IBindingService;
|
||||
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.springframework.tooling.boot.ls.prefs.CategoryProblemsSeverityPrefsPage;
|
||||
|
||||
/**
|
||||
* Boot-Java LS extension plugin
|
||||
@@ -51,7 +52,11 @@ public class BootLanguageServerPlugin extends AbstractUIPlugin {
|
||||
super.start(context);
|
||||
deactivateDuplicateKeybindings();
|
||||
BootJavaPreferencesPage.manageCodeMiningPreferences();
|
||||
|
||||
CategoryProblemsSeverityPrefsPage.loadProblemCategoriesIntoPreferences();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
|
||||
@@ -22,7 +22,6 @@ 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;
|
||||
@@ -32,6 +31,9 @@ import org.eclipse.lsp4j.InitializeResult;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Message;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage;
|
||||
import org.eclipse.lsp4j.services.LanguageServer;
|
||||
import org.springframework.tooling.boot.ls.prefs.CategoryProblemsSeverityPrefsPage;
|
||||
import org.springframework.tooling.boot.ls.prefs.ProblemCategoryData;
|
||||
import org.springframework.tooling.boot.ls.prefs.ProblemCategoryData.CategoryToggleData;
|
||||
import org.springframework.tooling.ls.eclipse.commons.LanguageServerCommonsActivator;
|
||||
import org.springsource.ide.eclipse.commons.boot.ls.remoteapps.RemoteBootAppsDataHolder;
|
||||
import org.springsource.ide.eclipse.commons.boot.ls.remoteapps.RemoteBootAppsDataHolder.RemoteAppData;
|
||||
@@ -194,6 +196,7 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
|
||||
settings.put("boot-java", bootJavaObj);
|
||||
|
||||
putValidationPreferences(settings);
|
||||
putValidationCategoryToggles(settings);
|
||||
|
||||
this.languageServer.getWorkspaceService().didChangeConfiguration(new DidChangeConfigurationParams(settings));
|
||||
}
|
||||
@@ -213,6 +216,23 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
|
||||
Log.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void putValidationCategoryToggles(Map<String, Object> settings) {
|
||||
try {
|
||||
IEclipsePreferences prefs = BootLanguageServerPlugin.getPreferences();
|
||||
for (ProblemCategoryData category : CategoryProblemsSeverityPrefsPage.ALL_PROBLEM_CATEGORIES) {
|
||||
if (category.getToggle() != null) {
|
||||
CategoryToggleData toggle = category.getToggle();
|
||||
String val = prefs.get(toggle.getPreferenceKey(), null);
|
||||
if (val != null) {
|
||||
dotPut(settings, toggle.getPreferenceKey(), val);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void dotPut(Object _settings, String dottedProperty, Object value) {
|
||||
if (_settings instanceof Map) {
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* 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.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("problem.properties.");
|
||||
|
||||
public ApplicationPropertiesEditorProblemSeverityPrefsPage() throws IOException {
|
||||
super(util, LanguageServerProblemTypesMetadata.load().get("application-properties"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPluginId() {
|
||||
return BootLanguageServerPlugin.PLUGIN_ID;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* 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("problem.yaml.");
|
||||
|
||||
public ApplicationYamlEditorProblemSeverityPrefsPage() throws IOException {
|
||||
super(util, LanguageServerProblemTypesMetadata.load().get("application-yaml"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPluginId() {
|
||||
return BootLanguageServerPlugin.PLUGIN_ID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, 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:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.tooling.boot.ls.prefs;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.runtime.preferences.DefaultScope;
|
||||
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
|
||||
import org.eclipse.jface.preference.ComboFieldEditor;
|
||||
import org.eclipse.jface.preference.PreferenceManager;
|
||||
import org.eclipse.jface.preference.PreferenceNode;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
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;
|
||||
import org.springframework.tooling.boot.ls.prefs.ProblemCategoryData.CategoryToggleData;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class CategoryProblemsSeverityPrefsPage extends ProblemSeverityPreferityPageFromMetadata {
|
||||
|
||||
public static ImmutableList<ProblemCategoryData> ALL_PROBLEM_CATEGORIES;
|
||||
|
||||
private static final String PREF_KEY_PREFIX = "";
|
||||
|
||||
private ProblemCategoryData category;
|
||||
|
||||
public CategoryProblemsSeverityPrefsPage(ProblemCategoryData category) {
|
||||
super(new ProblemSeverityPreferencesUtil("problem." + category.getId() + "."), category.getProblemTypes());
|
||||
this.category = category;
|
||||
setTitle(category.getLabel());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPluginId() {
|
||||
return BootLanguageServerPlugin.PLUGIN_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeDefaults() {
|
||||
if (category.getToggle() != null) {
|
||||
IEclipsePreferences defaults = DefaultScope.INSTANCE.getNode(getPluginId());
|
||||
defaults.put(PREF_KEY_PREFIX + category.getToggle().getPreferenceKey(), category.getToggle().getDefaultValue());
|
||||
|
||||
}
|
||||
super.initializeDefaults();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createFieldEditors() {
|
||||
if (category.getToggle() != null) {
|
||||
CategoryToggleData toggle = category.getToggle();
|
||||
ComboFieldEditor field = new ComboFieldEditor(
|
||||
PREF_KEY_PREFIX + toggle.getPreferenceKey(),
|
||||
toggle.getLabel(),
|
||||
createToggleValues(toggle.getValues()),
|
||||
getFieldEditorParent()
|
||||
);
|
||||
addField(field);
|
||||
}
|
||||
super.createFieldEditors();
|
||||
}
|
||||
|
||||
private static String[][] createToggleValues(String[] values) {
|
||||
String[][] res = new String[values.length][2];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
String value = values[i];
|
||||
res[i][0] = value.substring(0, 1).toUpperCase() + value.substring(1).toLowerCase();
|
||||
res[i][1] = value;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public static void loadProblemCategoriesIntoPreferences() throws Exception {
|
||||
List<ProblemCategoryData> categories = LanguageServerProblemTypesMetadata.load();
|
||||
|
||||
Collections.sort(categories, (e1, e2) -> e1.getOrder() - e2.getOrder());
|
||||
|
||||
for (ProblemCategoryData categoryData : categories) {
|
||||
|
||||
//create a new PreferenceNode that will appear in the Preference window
|
||||
PreferenceNode node = new PreferenceNode(BootLanguageServerPlugin.PLUGIN_ID + "." + categoryData.getId()) {
|
||||
|
||||
@Override
|
||||
public void createPage() {
|
||||
CategoryProblemsSeverityPrefsPage page = new CategoryProblemsSeverityPrefsPage(categoryData);
|
||||
page.init(PlatformUI.getWorkbench());
|
||||
page.setTitle(getLabelText());
|
||||
setPage(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabelText() {
|
||||
return categoryData.getLabel();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//use workbenches's preference manager
|
||||
PreferenceManager pm= PlatformUI.getWorkbench().getPreferenceManager();
|
||||
|
||||
pm.addTo("org.eclipse.lsp4e.preferences/org.springframework.tooling.ls.eclipse.commons.console.preferences/org.springframework.tooling.boot.ls.preferences", node); //add the node in the PreferenceManager
|
||||
}
|
||||
|
||||
ALL_PROBLEM_CATEGORIES = ImmutableList.copyOf(categories);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2020 Pivotal, Inc.
|
||||
* Copyright (c) 2020, 2022 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
|
||||
@@ -11,19 +11,35 @@
|
||||
package org.springframework.tooling.boot.ls.prefs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.io.Reader;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.runtime.FileLocator;
|
||||
import org.springframework.ide.eclipse.editor.support.preferences.ProblemSeverityPreferityPageFromMetadata.ProblemTypeData;
|
||||
import org.springframework.tooling.boot.ls.BootLanguageServerPlugin;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class LanguageServerProblemTypesMetadata {
|
||||
|
||||
public static Map<String, ProblemTypeData[]> load() throws IOException {
|
||||
public static List<ProblemCategoryData> 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);
|
||||
return readCategoriesFromFile(metadataFile);
|
||||
}
|
||||
|
||||
public static List<ProblemCategoryData> readCategoriesFromFile(File metadataFile) throws FileNotFoundException, IOException {
|
||||
Gson gson = new Gson();
|
||||
TypeToken<List<ProblemCategoryData>> tt = new TypeToken<List<ProblemCategoryData>>() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
};
|
||||
try (Reader json = new FileReader(metadataFile)) {
|
||||
return gson.fromJson(json, tt.getType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, 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:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.tooling.boot.ls.prefs;
|
||||
|
||||
import org.springframework.ide.eclipse.editor.support.preferences.ProblemSeverityPreferityPageFromMetadata.ProblemTypeData;
|
||||
|
||||
public class ProblemCategoryData {
|
||||
private String id;
|
||||
private String label;
|
||||
private String description;
|
||||
private CategoryToggleData toggle;
|
||||
private int order;
|
||||
private ProblemTypeData[] problemTypes;
|
||||
|
||||
ProblemCategoryData() {}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public CategoryToggleData getToggle() {
|
||||
return toggle;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public ProblemTypeData[] getProblemTypes() {
|
||||
return problemTypes;
|
||||
}
|
||||
|
||||
public static class CategoryToggleData {
|
||||
private String label;
|
||||
|
||||
private String[] values;
|
||||
|
||||
private String preferenceKey;
|
||||
|
||||
private String defaultValue;
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public String[] getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public String getPreferenceKey() {
|
||||
return preferenceKey;
|
||||
}
|
||||
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* 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 SpringJavaProblemSeverityPrefsPage extends ProblemSeverityPreferityPageFromMetadata {
|
||||
|
||||
public static final ProblemSeverityPreferencesUtil util = new ProblemSeverityPreferencesUtil("problem.java.");
|
||||
|
||||
public SpringJavaProblemSeverityPrefsPage() throws IOException {
|
||||
super(util, LanguageServerProblemTypesMetadata.load().get("java"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPluginId() {
|
||||
return BootLanguageServerPlugin.PLUGIN_ID;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -130,7 +130,7 @@ public class BoshCloudConfigSchema extends SchemaSupport implements YamlSchema {
|
||||
|
||||
ASTTypeCache astTypes = models.astTypes;
|
||||
for (YType defType : getDefinitionTypes()) {
|
||||
toplevelType.require(Constraints.uniqueDefinition(astTypes, defType, YamlSchemaProblems.problemType("BOSH_CC_DUPLICATE_"+defType)));
|
||||
toplevelType.require(Constraints.uniqueDefinition(astTypes, defType, YamlSchemaProblems.problemType("BOSH_CC_DUPLICATE_"+defType, BoshSchemaProblems.CATEGORY)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -321,7 +321,7 @@ public class BoshDeploymentManifestSchema extends SchemaSupport implements YamlS
|
||||
}
|
||||
|
||||
for (YType defType : getDefinitionTypes()) {
|
||||
v2Schema.require(Constraints.uniqueDefinition(this.astTypes, defType, YamlSchemaProblems.problemType("BOSH_DUPLICATE_"+defType)));
|
||||
v2Schema.require(Constraints.uniqueDefinition(this.astTypes, defType, YamlSchemaProblems.problemType("BOSH_DUPLICATE_"+defType, BoshSchemaProblems.CATEGORY)));
|
||||
}
|
||||
return v2Schema;
|
||||
}
|
||||
|
||||
@@ -10,12 +10,15 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.bosh;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
import org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaProblems;
|
||||
|
||||
public class BoshSchemaProblems {
|
||||
|
||||
public static final ProblemCategory CATEGORY = new ProblemCategory("bosh", "Bosh YAML Validation", null);
|
||||
|
||||
public static final ProblemType MISSING_SHA1_PROPERTY = YamlSchemaProblems.problemType("MISSING_SHA1_PROPERTY", ProblemSeverity.WARNING);
|
||||
public static final ProblemType MISSING_SHA1_PROPERTY = YamlSchemaProblems.problemType("MISSING_SHA1_PROPERTY", ProblemSeverity.WARNING, CATEGORY);
|
||||
|
||||
}
|
||||
|
||||
@@ -46,6 +46,11 @@ public class BadWordReconcileEngine implements IReconcileEngine {
|
||||
public String getLabel() {
|
||||
return "Bad label";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemCategory getCategory() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final String[] BADWORDS = {
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, 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:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.languageserver.reconcile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public final class ProblemCategory {
|
||||
|
||||
private static AtomicInteger counter = new AtomicInteger();
|
||||
|
||||
public static final ProblemCategory NO_CATEGORY = new ProblemCategory("uncategorized", "Uncategorized", null);
|
||||
|
||||
final private String id;
|
||||
|
||||
final private String label;
|
||||
|
||||
final private List<ProblemType> problemTypes = new ArrayList<>();;
|
||||
|
||||
final private Toggle toggle;
|
||||
|
||||
final public int order;
|
||||
|
||||
public ProblemCategory(String id, String label, Toggle toggle) {
|
||||
this.id = id;
|
||||
this.label = label;
|
||||
this.toggle = toggle;
|
||||
this.order = counter.getAndIncrement();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public List<ProblemType> getProblemTypes() {
|
||||
return problemTypes;
|
||||
}
|
||||
|
||||
public Toggle getToggle() {
|
||||
return toggle;
|
||||
}
|
||||
|
||||
public static final class Toggle {
|
||||
|
||||
public enum Option {
|
||||
AUTO,
|
||||
OFF,
|
||||
ON
|
||||
}
|
||||
|
||||
private final String label;
|
||||
|
||||
private final EnumSet<Option> values;
|
||||
|
||||
private final String preferenceKey;
|
||||
|
||||
private final Option defaultValue;
|
||||
|
||||
public Toggle(String label, EnumSet<Option> values, Option defaultValue, String preferenceKey) {
|
||||
this.label = label;
|
||||
this.values = values;
|
||||
this.defaultValue = defaultValue;
|
||||
this.preferenceKey = preferenceKey;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public EnumSet<Option> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public String getPreferenceKey() {
|
||||
return preferenceKey;
|
||||
}
|
||||
|
||||
public Option getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,4 +28,5 @@ public interface ProblemType {
|
||||
String getCode();
|
||||
String getLabel();
|
||||
String getDescription();
|
||||
ProblemCategory getCategory();
|
||||
}
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.languageserver.reconcile;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
|
||||
public class ProblemTypes {
|
||||
|
||||
/**
|
||||
@@ -28,7 +24,7 @@ public class ProblemTypes {
|
||||
* @return A newly create problem type.
|
||||
*/
|
||||
@Deprecated
|
||||
public static ProblemType create(String typeName, ProblemSeverity defaultSeverity) {
|
||||
public static ProblemType create(String typeName, ProblemSeverity defaultSeverity, ProblemCategory category) {
|
||||
return new ProblemType() {
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -50,6 +46,10 @@ public class ProblemTypes {
|
||||
public String getLabel() {
|
||||
return typeName;
|
||||
}
|
||||
@Override
|
||||
public ProblemCategory getCategory() {
|
||||
return category;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, 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:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.rewrite.java;
|
||||
|
||||
import org.openrewrite.Cursor;
|
||||
import org.openrewrite.ExecutionContext;
|
||||
import org.openrewrite.Recipe;
|
||||
import org.openrewrite.TreeVisitor;
|
||||
import org.openrewrite.java.JavaIsoVisitor;
|
||||
import org.openrewrite.java.search.UsesType;
|
||||
import org.openrewrite.java.tree.J;
|
||||
import org.openrewrite.java.tree.JavaType;
|
||||
import org.openrewrite.java.tree.TypeTree;
|
||||
import org.openrewrite.java.tree.TypeUtils;
|
||||
|
||||
public class PreciseBeanType extends Recipe {
|
||||
|
||||
private final static String BEAN = "org.springframework.context.annotation.Bean";
|
||||
|
||||
private final static String MSG_KEY = "returnType";
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "Replace Bean method return types with concrete types being returned. This is required for Spring 6 AOT";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TreeVisitor<?, ExecutionContext> getSingleSourceApplicableTest() {
|
||||
return new UsesType<ExecutionContext>(BEAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TreeVisitor<?, ExecutionContext> getVisitor() {
|
||||
return new JavaIsoVisitor<ExecutionContext>() {
|
||||
@Override
|
||||
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext executionContext) {
|
||||
J.MethodDeclaration m = super.visitMethodDeclaration(method, executionContext);
|
||||
if (isBeanMethod(m)) {
|
||||
Object o = getCursor().pollMessage(MSG_KEY);
|
||||
if (o != null) {
|
||||
if (!o.equals(method.getReturnTypeExpression().getType())) {
|
||||
if (o instanceof JavaType.FullyQualified) {
|
||||
JavaType.FullyQualified actualType = (JavaType.FullyQualified) o;
|
||||
if (m.getReturnTypeExpression() instanceof J.Identifier) {
|
||||
J.Identifier identifierReturnExpr = (J.Identifier) m.getReturnTypeExpression();
|
||||
maybeAddImport(actualType);
|
||||
if (identifierReturnExpr.getType() instanceof JavaType.FullyQualified) {
|
||||
maybeRemoveImport((JavaType.FullyQualified) identifierReturnExpr.getType());
|
||||
}
|
||||
m = m.withReturnTypeExpression(identifierReturnExpr
|
||||
.withType(actualType)
|
||||
.withSimpleName(actualType.getClassName())
|
||||
);
|
||||
} else if (m.getReturnTypeExpression() instanceof J.ParameterizedType) {
|
||||
J.ParameterizedType parameterizedType = (J.ParameterizedType) m.getReturnTypeExpression();
|
||||
maybeAddImport(actualType);
|
||||
if (parameterizedType.getType() instanceof JavaType.FullyQualified) {
|
||||
maybeRemoveImport((JavaType.FullyQualified) parameterizedType.getType());
|
||||
}
|
||||
m = m.withReturnTypeExpression(parameterizedType
|
||||
.withType(actualType)
|
||||
.withClazz(TypeTree.build(actualType.getClassName()).withType(actualType))
|
||||
);
|
||||
}
|
||||
|
||||
} else if (o instanceof JavaType.Array) {
|
||||
JavaType.Array actualType = (JavaType.Array) o;
|
||||
if (m.getReturnTypeExpression() instanceof J.ArrayType && actualType.getElemType() instanceof JavaType.FullyQualified) {
|
||||
JavaType.FullyQualified actualElementType = (JavaType.FullyQualified) actualType.getElemType();
|
||||
J.ArrayType arrayType = (J.ArrayType) m.getReturnTypeExpression();
|
||||
maybeAddImport(actualElementType);
|
||||
if (arrayType.getElementType() instanceof JavaType.FullyQualified) {
|
||||
maybeRemoveImport((JavaType.FullyQualified) arrayType.getElementType());
|
||||
}
|
||||
m = m.withReturnTypeExpression(arrayType
|
||||
.withElementType(TypeTree.build(actualElementType.getClassName()).withType(actualType))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
private boolean isBeanMethod(J.MethodDeclaration m) {
|
||||
return m.getLeadingAnnotations().stream().anyMatch(a -> TypeUtils.isOfClassType(a.getType(), BEAN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public J.Return visitReturn(J.Return _return, ExecutionContext executionContext) {
|
||||
Cursor methodCursor = getCursor();
|
||||
while (methodCursor != null && !(methodCursor.getValue() instanceof J.Lambda || methodCursor.getValue() instanceof J.MethodDeclaration)) {
|
||||
methodCursor = methodCursor.getParent();
|
||||
}
|
||||
if (methodCursor != null && methodCursor.getValue() instanceof J.MethodDeclaration) {
|
||||
methodCursor.putMessage(MSG_KEY, _return.getExpression().getType());
|
||||
}
|
||||
return super.visitReturn(_return, executionContext);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.Quickfix.QuickfixData;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixType;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory;
|
||||
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.ProblemTypes;
|
||||
@@ -46,25 +47,27 @@ import com.google.common.collect.ImmutableSet;
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class YamlSchemaProblems {
|
||||
|
||||
public static final ProblemCategory CATEGORY = new ProblemCategory("yaml-schema-problems", "YAML Shema Problems", null);
|
||||
|
||||
public static final ProblemType SYNTAX_PROBLEM = problemType("YamlSyntaxProblem");
|
||||
public static final ProblemType SCHEMA_PROBLEM = problemType("YamlSchemaProblem");
|
||||
public static final ProblemType DEPRECATED_PROPERTY = problemType("DeprecatedProperty", ProblemSeverity.WARNING);
|
||||
public static final ProblemType DEPRECATED_VALUE = problemType("DeprecatedValue", ProblemSeverity.WARNING);
|
||||
public static final ProblemType MISSING_PROPERTY = problemType("MissingProperty", ProblemSeverity.ERROR);
|
||||
public static final ProblemType EXTRA_PROPERTY = problemType("ExtraProperty", ProblemSeverity.ERROR);
|
||||
public static final ProblemType EMPTY_OPTIONAL_STRING = problemType("EmptyOptionalString", ProblemSeverity.WARNING);
|
||||
public static final ProblemType SYNTAX_PROBLEM = problemType("YamlSyntaxProblem", CATEGORY);
|
||||
public static final ProblemType SCHEMA_PROBLEM = problemType("YamlSchemaProblem", CATEGORY);
|
||||
public static final ProblemType DEPRECATED_PROPERTY = problemType("DeprecatedProperty", ProblemSeverity.WARNING, CATEGORY);
|
||||
public static final ProblemType DEPRECATED_VALUE = problemType("DeprecatedValue", ProblemSeverity.WARNING, CATEGORY);
|
||||
public static final ProblemType MISSING_PROPERTY = problemType("MissingProperty", ProblemSeverity.ERROR, CATEGORY);
|
||||
public static final ProblemType EXTRA_PROPERTY = problemType("ExtraProperty", ProblemSeverity.ERROR, CATEGORY);
|
||||
public static final ProblemType EMPTY_OPTIONAL_STRING = problemType("EmptyOptionalString", ProblemSeverity.WARNING, CATEGORY);
|
||||
|
||||
public static final Set<ProblemType> PROPERTY_CONSTRAINT = ImmutableSet.of(
|
||||
MISSING_PROPERTY, EXTRA_PROPERTY
|
||||
);
|
||||
|
||||
public static ProblemType problemType(final String typeName, ProblemSeverity defaultSeverity) {
|
||||
return ProblemTypes.create(typeName, defaultSeverity);
|
||||
public static ProblemType problemType(final String typeName, ProblemSeverity defaultSeverity, ProblemCategory category) {
|
||||
return ProblemTypes.create(typeName, defaultSeverity, category);
|
||||
}
|
||||
|
||||
public static ProblemType problemType(final String typeName) {
|
||||
return problemType(typeName, ProblemSeverity.ERROR);
|
||||
public static ProblemType problemType(final String typeName, ProblemCategory category) {
|
||||
return problemType(typeName, ProblemSeverity.ERROR, category);
|
||||
}
|
||||
|
||||
public static ReconcileProblem syntaxProblem(String msg, int offset, int len) {
|
||||
|
||||
@@ -10,12 +10,15 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.concourse;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaProblems.*;
|
||||
|
||||
public class PipelineYmlSchemaProblems {
|
||||
public static final ProblemType UNUSED_RESOURCE = problemType("PipelineYamlUnusedResource", ProblemSeverity.ERROR);
|
||||
public static final ProblemType UNKNOWN_GITHUB_ENTITY = problemType("UnknownGithubEntitity", ProblemSeverity.WARNING);
|
||||
|
||||
public static final ProblemCategory CATEGORY = new ProblemCategory("concourse", "Concource YAML Validation", null);
|
||||
public static final ProblemType UNUSED_RESOURCE = problemType("PipelineYamlUnusedResource", ProblemSeverity.ERROR, CATEGORY);
|
||||
public static final ProblemType UNKNOWN_GITHUB_ENTITY = problemType("UnknownGithubEntitity", ProblemSeverity.WARNING, CATEGORY);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ package org.springframework.ide.vscode.manifest.yaml;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaProblems.problemType;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
|
||||
@@ -20,11 +21,12 @@ import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemTy
|
||||
*/
|
||||
public class ManifestYamlSchemaProblemsTypes {
|
||||
|
||||
public static final ProblemType UNKNOWN_SERVICES_PROBLEM = problemType("UnknownServicesProblem", ProblemSeverity.WARNING);
|
||||
public static final ProblemType UNKNOWN_DOMAIN_PROBLEM = problemType("UnknownDomainProblem", ProblemSeverity.WARNING);
|
||||
public static final ProblemType UNKNOWN_STACK_PROBLEM = problemType("UnknownStackProblem", ProblemSeverity.WARNING);
|
||||
public static final ProblemType IGNORED_PROPERTY = problemType("IgnoredProperty", ProblemSeverity.WARNING);
|
||||
public static final ProblemCategory CATEGORY = new ProblemCategory("manifest", "CF Manifest YAML Validation", null);
|
||||
public static final ProblemType UNKNOWN_SERVICES_PROBLEM = problemType("UnknownServicesProblem", ProblemSeverity.WARNING, CATEGORY);
|
||||
public static final ProblemType UNKNOWN_DOMAIN_PROBLEM = problemType("UnknownDomainProblem", ProblemSeverity.WARNING, CATEGORY);
|
||||
public static final ProblemType UNKNOWN_STACK_PROBLEM = problemType("UnknownStackProblem", ProblemSeverity.WARNING, CATEGORY);
|
||||
public static final ProblemType IGNORED_PROPERTY = problemType("IgnoredProperty", ProblemSeverity.WARNING, CATEGORY);
|
||||
public static final ProblemType MUTUALLY_EXCLUSIVE_PROPERTY_PROBLEM = problemType("MutuallyExclusiveProperty",
|
||||
ProblemSeverity.ERROR);
|
||||
ProblemSeverity.ERROR, CATEGORY);
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,12 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.ide.vscode.boot.common.SpringProblemCategories;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory.Toggle;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.ListenerList;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.Settings;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
@@ -30,6 +35,8 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
public class BootJavaConfig implements InitializingBean {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BootJavaConfig.class);
|
||||
|
||||
public static final boolean LIVE_INFORMATION_AUTOMATIC_TRACKING_ENABLED_DEFAULT = false;
|
||||
public static final int LIVE_INFORMATION_AUTOMATIC_TRACKING_DELAY_DEFAULT = 5000;
|
||||
|
||||
@@ -110,8 +117,17 @@ public class BootJavaConfig implements InitializingBean {
|
||||
}
|
||||
|
||||
public boolean isSpelExpressionValidationEnabled() {
|
||||
Boolean enabled = settings.getBoolean("boot-java", "validation", "spel", "on");
|
||||
return enabled != null ? enabled.booleanValue() : VALIDAITON_SPEL_EXPRESSIONS_ENABLED_DEFAULT;
|
||||
Toggle categorySwitch = SpringProblemCategories.SPEL.getToggle();
|
||||
String enabled = settings.getString(categorySwitch.getPreferenceKey().split("\\."));
|
||||
if (enabled == null) {
|
||||
return categorySwitch.getDefaultValue() == Toggle.Option.ON;
|
||||
} else {
|
||||
// Legacy case
|
||||
if ("true".equalsIgnoreCase(enabled)) {
|
||||
return true;
|
||||
}
|
||||
return Toggle.Option.valueOf(enabled) == Toggle.Option.ON;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean areXmlHyperlinksEnabled() {
|
||||
@@ -147,4 +163,18 @@ public class BootJavaConfig implements InitializingBean {
|
||||
public Settings getRawSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
public Toggle.Option getProblemApplicability(ProblemType problem) {
|
||||
try {
|
||||
if (problem != null && problem.getCategory() != null && problem.getCategory().getToggle() != null) {
|
||||
Toggle toggle = problem.getCategory().getToggle();
|
||||
String s = settings.getString((toggle.getPreferenceKey()).split("\\."));
|
||||
return s == null || s.isEmpty() ? toggle.getDefaultValue() : Toggle.Option.valueOf(s);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
return Toggle.Option.AUTO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, 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:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.common;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory.Toggle;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory.Toggle.Option.*;
|
||||
|
||||
public class SpringProblemCategories {
|
||||
|
||||
public static final ProblemCategory BOOT_2 = new ProblemCategory("boot2", "Boot 2.x Validation",
|
||||
new Toggle("Enablement", EnumSet.allOf(Toggle.Option.class), AUTO, "boot-java.validation.java.boot2"));
|
||||
|
||||
public static final ProblemCategory BOOT_3 = new ProblemCategory("boot3", "Boot 3.x Validation",
|
||||
new Toggle("Enablement", EnumSet.allOf(Toggle.Option.class), AUTO, "boot-java.validation.java.boot3"));
|
||||
|
||||
public static final ProblemCategory PROPERTIES = new ProblemCategory("application-properties", "Properties Validation", null);
|
||||
|
||||
public static final ProblemCategory YAML = new ProblemCategory("application-yaml", "YAML Properties Validation", null);
|
||||
|
||||
public static final ProblemCategory SPEL = new ProblemCategory("spel", "SPEL Validation",
|
||||
new Toggle("Enablement", EnumSet.of(OFF, ON), ON, "boot-java.validation.spel.on"));
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,29 +1,25 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2020, 2022 Pivotal, Inc.
|
||||
* Copyright (c) 2022 VMware, 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
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.HINT;
|
||||
import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.WARNING;
|
||||
|
||||
import org.springframework.ide.vscode.boot.common.SpringProblemCategories;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.*;
|
||||
public enum Boot2JavaProblemType implements ProblemType {
|
||||
|
||||
/**
|
||||
* This enum is supposed to represent *all* the different types of problems SpringBoot language server
|
||||
* may detect in Java code.
|
||||
*/
|
||||
public enum SpringJavaProblemType implements ProblemType {
|
||||
|
||||
JAVA_SPEL_EXPRESSION_SYNTAX(ERROR, "SpEL parser raised a ParseException", "SpEL Expression Syntax"),
|
||||
|
||||
JAVA_AUTOWIRED_CONSTRUCTOR(WARNING, "Unnecessary `@Autowired` over the only constructor", "Unnecessary `@Autowired`"),
|
||||
|
||||
JAVA_PUBLIC_BEAN_METHOD(HINT, "Public modifier on `@Bean` method. They no longer have to be public visibility to be usable by Spring.", "public `@Bean` method"),
|
||||
@@ -34,15 +30,14 @@ public enum SpringJavaProblemType implements ProblemType {
|
||||
private String description;
|
||||
private String label;
|
||||
|
||||
private SpringJavaProblemType(ProblemSeverity defaultSeverity, String description) {
|
||||
private Boot2JavaProblemType(ProblemSeverity defaultSeverity, String description) {
|
||||
this(defaultSeverity, description, null);
|
||||
}
|
||||
|
||||
private SpringJavaProblemType(ProblemSeverity defaultSeverity, String description, String label) {
|
||||
private Boot2JavaProblemType(ProblemSeverity defaultSeverity, String description, String label) {
|
||||
this.description = description;
|
||||
this.defaultSeverity = defaultSeverity;
|
||||
this.label = label;
|
||||
Assert.isLegal(name().startsWith("JAVA_"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,4 +67,9 @@ public enum SpringJavaProblemType implements ProblemType {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemCategory getCategory() {
|
||||
return SpringProblemCategories.BOOT_2;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2020, 2022 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.java;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.WARNING;
|
||||
|
||||
import org.springframework.ide.vscode.boot.common.SpringProblemCategories;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
|
||||
/**
|
||||
* This enum is supposed to represent *all* the different types of problems SpringBoot language server
|
||||
* may detect in Java code.
|
||||
*/
|
||||
public enum Boot3JavaProblemType implements ProblemType {
|
||||
|
||||
JAVA_CONCRETE_BEAN_TYPE(WARNING, "Bean definition should have precise type for Spring 6 AOT", "Not precise bean defintion type");
|
||||
|
||||
private final ProblemSeverity defaultSeverity;
|
||||
private String description;
|
||||
private String label;
|
||||
|
||||
private Boot3JavaProblemType(ProblemSeverity defaultSeverity, String description) {
|
||||
this(defaultSeverity, description, null);
|
||||
}
|
||||
|
||||
private Boot3JavaProblemType(ProblemSeverity defaultSeverity, String description, String label) {
|
||||
this.description = description;
|
||||
this.defaultSeverity = defaultSeverity;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemSeverity getDefaultSeverity() {
|
||||
return defaultSeverity;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
if (label==null) {
|
||||
label = createDefaultLabel();
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
private String createDefaultLabel() {
|
||||
String label = this.toString().substring(5).toLowerCase().replace('_', ' ');
|
||||
return Character.toUpperCase(label.charAt(0)) + label.substring(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemCategory getCategory() {
|
||||
return SpringProblemCategories.BOOT_3;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, 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:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.ERROR;
|
||||
|
||||
import org.springframework.ide.vscode.boot.common.SpringProblemCategories;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
|
||||
public enum SpelProblemType implements ProblemType {
|
||||
|
||||
JAVA_SPEL_EXPRESSION_SYNTAX(ERROR, "SpEL parser raised a ParseException", "SpEL Expression Syntax");
|
||||
|
||||
private final ProblemSeverity defaultSeverity;
|
||||
private String description;
|
||||
private String label;
|
||||
|
||||
private SpelProblemType(ProblemSeverity defaultSeverity, String description) {
|
||||
this(defaultSeverity, description, null);
|
||||
}
|
||||
|
||||
private SpelProblemType(ProblemSeverity defaultSeverity, String description, String label) {
|
||||
this.description = description;
|
||||
this.defaultSeverity = defaultSeverity;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemSeverity getDefaultSeverity() {
|
||||
return defaultSeverity;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
if (label==null) {
|
||||
label = createDefaultLabel();
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
private String createDefaultLabel() {
|
||||
String label = this.toString().substring(5).toLowerCase().replace('_', ' ');
|
||||
return Character.toUpperCase(label.charAt(0)) + label.substring(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemCategory getCategory() {
|
||||
return SpringProblemCategories.SPEL;
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,8 @@ package org.springframework.ide.vscode.boot.java.handlers;
|
||||
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.ide.vscode.boot.java.SpringJavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.SpelProblemType;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemTypes;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
|
||||
import org.springframework.util.SystemPropertyUtils;
|
||||
@@ -58,7 +56,7 @@ 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(SpringJavaProblemType.JAVA_SPEL_EXPRESSION_SYNTAX, message, start, length);
|
||||
ReconcileProblem problem = new ReconcileProblemImpl(SpelProblemType.JAVA_SPEL_EXPRESSION_SYNTAX, message, start, length);
|
||||
problemCollector.accept(problem);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.SpringJavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchies;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
|
||||
@@ -48,7 +48,7 @@ public class AutowiredConstructorReconciler implements AnnotationReconciler {
|
||||
|
||||
if (version.getMajor() >= 2) {
|
||||
getSingleAutowiredConstructorDeclaringType(node, typeBinding).ifPresent(type -> {
|
||||
ReconcileProblemImpl problem = new ReconcileProblemImpl(SpringJavaProblemType.JAVA_AUTOWIRED_CONSTRUCTOR, "Unnecesary @Autowired", node.getStartPosition(), node.getLength());
|
||||
ReconcileProblemImpl problem = new ReconcileProblemImpl(Boot2JavaProblemType.JAVA_AUTOWIRED_CONSTRUCTOR, "Unnecesary @Autowired", node.getStartPosition(), node.getLength());
|
||||
QuickfixType quickfixType = quickfixRegistry.getQuickfixType(AutowiredConstructorReconciler.REMOVE_UNNECESSARY_AUTOWIRED_FROM_CONSTRUCTOR);
|
||||
if (quickfixType != null) {
|
||||
problem.addQuickfix(new QuickfixData<>(
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.eclipse.jdt.core.dom.Modifier;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.SpringJavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
|
||||
import org.springframework.ide.vscode.commons.java.Version;
|
||||
@@ -63,10 +63,10 @@ public class BeanMethodNotPublicReconciler implements AnnotationReconciler {
|
||||
.filter(modifier -> modifier.isPublic())
|
||||
.findFirst()
|
||||
.map(modifier -> new ReconcileProblemImpl(
|
||||
SpringJavaProblemType.JAVA_PUBLIC_BEAN_METHOD, "public @Bean method",
|
||||
Boot2JavaProblemType.JAVA_PUBLIC_BEAN_METHOD, "public @Bean method",
|
||||
modifier.getStartPosition(), modifier.getLength()))
|
||||
.orElse(new ReconcileProblemImpl(
|
||||
SpringJavaProblemType.JAVA_PUBLIC_BEAN_METHOD, "public @Bean method",
|
||||
Boot2JavaProblemType.JAVA_PUBLIC_BEAN_METHOD, "public @Bean method",
|
||||
m.getName().getStartPosition(), m.getName().getLength()));
|
||||
|
||||
QuickfixType quickfixType = quickfixRegistry.getQuickfixType(REMOVE_PUBLIC_FROM_BEAN_METHOD);
|
||||
|
||||
@@ -53,6 +53,7 @@ import org.springframework.ide.vscode.boot.java.rewrite.codeaction.BeanMethodsNo
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.NoRequestMappingAnnotationCodeAction;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.UnnecessarySpringExtensionCodeAction;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.BeanMethodNotPublicProblem;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.PreciseBeanTypeProblem;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.NoAutowiredOnConstructorProblem;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.RecipeSpringJavaProblemDescriptor;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.UnnecessarySpringExtensionProblem;
|
||||
@@ -113,7 +114,8 @@ public class RewriteRecipeRepository {
|
||||
private List<RecipeSpringJavaProblemDescriptor> javaProblemDescriptors = List.of(
|
||||
new BeanMethodNotPublicProblem(),
|
||||
new NoAutowiredOnConstructorProblem(),
|
||||
new UnnecessarySpringExtensionProblem()
|
||||
new UnnecessarySpringExtensionProblem(),
|
||||
new PreciseBeanTypeProblem()
|
||||
);
|
||||
|
||||
public RewriteRecipeRepository(SimpleLanguageServer server, JavaProjectFinder projectFinder) {
|
||||
|
||||
@@ -19,7 +19,6 @@ import java.util.stream.Collectors;
|
||||
import org.openrewrite.ExecutionContext;
|
||||
import org.openrewrite.InMemoryExecutionContext;
|
||||
import org.openrewrite.Tree;
|
||||
import org.openrewrite.internal.lang.Nullable;
|
||||
import org.openrewrite.java.JavaIsoVisitor;
|
||||
import org.openrewrite.java.tree.J;
|
||||
import org.openrewrite.java.tree.J.CompilationUnit;
|
||||
@@ -27,15 +26,16 @@ import org.openrewrite.marker.Range;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
|
||||
import org.springframework.ide.vscode.boot.java.SpringJavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.JavaReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings.Data;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.RecipeSpringJavaProblemDescriptor;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.Quickfix.QuickfixData;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixRegistry;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixType;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
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;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
|
||||
@@ -52,20 +52,20 @@ public class RewriteReconciler implements JavaReconciler {
|
||||
private RewriteRecipeRepository recipeRepo;
|
||||
|
||||
private BootJavaConfig config;
|
||||
|
||||
|
||||
public RewriteReconciler(RewriteRecipeRepository recipeRepo, RewriteCompilationUnitCache cuCache, QuickfixRegistry quickfixRegistry, BootJavaConfig config) {
|
||||
this.recipeRepo = recipeRepo;
|
||||
this.cuCache = cuCache;
|
||||
this.quickfixRegistry = quickfixRegistry;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void reconcile(IJavaProject project, IDocument doc, IProblemCollector problemCollector) {
|
||||
if (!config.isRewriteReconcileEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
problemCollector.beginCollecting();
|
||||
|
||||
@@ -73,7 +73,17 @@ public class RewriteReconciler implements JavaReconciler {
|
||||
recipeRepo.loaded.get();
|
||||
|
||||
List<RecipeSpringJavaProblemDescriptor> descriptors = recipeRepo.getProblemRecipeDescriptors().stream()
|
||||
.filter(d -> d.isApplicable(project))
|
||||
.filter(d -> d.getProblemType() != null)
|
||||
.filter(d -> {
|
||||
switch (config.getProblemApplicability(d.getProblemType())) {
|
||||
case ON:
|
||||
return SpringProjectUtil.isBootProject(project);
|
||||
case OFF:
|
||||
return false;
|
||||
default: // AUTO
|
||||
return d.isApplicable(project);
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!descriptors.isEmpty()) {
|
||||
@@ -86,7 +96,7 @@ public class RewriteReconciler implements JavaReconciler {
|
||||
new JavaIsoVisitor<ExecutionContext>() {
|
||||
|
||||
@Override
|
||||
public @Nullable J visit(@Nullable Tree tree, ExecutionContext context) {
|
||||
public J visit(Tree tree, ExecutionContext context) {
|
||||
J t = super.visit(tree, context);
|
||||
if (t instanceof J) {
|
||||
List<FixAssistMarker> markers = t.getMarkers().findAll(FixAssistMarker.class);
|
||||
@@ -125,7 +135,7 @@ public class RewriteReconciler implements JavaReconciler {
|
||||
|
||||
private ReconcileProblemImpl createProblemFromScope(IDocument doc, RecipeSpringJavaProblemDescriptor recipeFixDescriptor, RecipeScope s,
|
||||
FixAssistMarker m, Range range) {
|
||||
SpringJavaProblemType problemType = recipeFixDescriptor.getProblemType();
|
||||
ProblemType problemType = recipeFixDescriptor.getProblemType();
|
||||
ReconcileProblemImpl problem = new ReconcileProblemImpl(problemType, problemType.getLabel(), range.getStart().getOffset(), range.getEnd().getOffset() - range.getStart().getOffset());
|
||||
QuickfixType quickfixType = quickfixRegistry.getQuickfixType(m.getRecipeId());
|
||||
if (quickfixType != null) {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.rewrite.reconcile;
|
||||
|
||||
import org.springframework.ide.vscode.boot.java.SpringJavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeScope;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.BeanMethodsNotPublicCodeAction;
|
||||
|
||||
@@ -22,8 +22,8 @@ public class BeanMethodNotPublicProblem extends BeanMethodsNotPublicCodeAction i
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpringJavaProblemType getProblemType() {
|
||||
return SpringJavaProblemType.JAVA_PUBLIC_BEAN_METHOD;
|
||||
public Boot2JavaProblemType getProblemType() {
|
||||
return Boot2JavaProblemType.JAVA_PUBLIC_BEAN_METHOD;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@ import org.openrewrite.internal.ListUtils;
|
||||
import org.openrewrite.java.JavaIsoVisitor;
|
||||
import org.openrewrite.java.JavaVisitor;
|
||||
import org.openrewrite.java.tree.J;
|
||||
import org.openrewrite.java.tree.Statement;
|
||||
import org.openrewrite.java.tree.TypeUtils;
|
||||
import org.openrewrite.java.tree.J.ClassDeclaration;
|
||||
import org.openrewrite.java.tree.J.MethodDeclaration;
|
||||
import org.openrewrite.java.tree.JavaType.FullyQualified;
|
||||
import org.openrewrite.java.tree.Statement;
|
||||
import org.openrewrite.java.tree.TypeUtils;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.SpringJavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.AnnotationHierarchies;
|
||||
@@ -105,8 +105,8 @@ public class NoAutowiredOnConstructorProblem implements RecipeSpringJavaProblemD
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpringJavaProblemType getProblemType() {
|
||||
return SpringJavaProblemType.JAVA_AUTOWIRED_CONSTRUCTOR;
|
||||
public Boot2JavaProblemType getProblemType() {
|
||||
return Boot2JavaProblemType.JAVA_AUTOWIRED_CONSTRUCTOR;
|
||||
}
|
||||
|
||||
private static boolean isConstructor(Statement s) {
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, 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:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.rewrite.reconcile;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.java.SpringProjectUtil.springBootVersionGreaterOrEqual;
|
||||
|
||||
import org.openrewrite.Cursor;
|
||||
import org.openrewrite.ExecutionContext;
|
||||
import org.openrewrite.Tree;
|
||||
import org.openrewrite.java.JavaIsoVisitor;
|
||||
import org.openrewrite.java.JavaVisitor;
|
||||
import org.openrewrite.java.tree.J;
|
||||
import org.openrewrite.java.tree.J.Return;
|
||||
import org.openrewrite.java.tree.JavaType;
|
||||
import org.openrewrite.java.tree.TypeUtils;
|
||||
import org.springframework.ide.vscode.boot.java.Boot3JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
|
||||
|
||||
public class PreciseBeanTypeProblem implements RecipeSpringJavaProblemDescriptor {
|
||||
|
||||
private static final String LABEL = "Ensure concrete bean type";
|
||||
|
||||
private static final String MSG_KEY = "returnType";
|
||||
|
||||
@Override
|
||||
public String getRecipeId() {
|
||||
return "org.springframework.ide.vscode.commons.rewrite.java.PreciseBeanType";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel(RecipeScope s) {
|
||||
return RecipeCodeActionDescriptor.buildLabel(LABEL, s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeScope[] getScopes() {
|
||||
return RecipeScope.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaVisitor<ExecutionContext> getMarkerVisitor() {
|
||||
return new JavaIsoVisitor<>() {
|
||||
|
||||
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext executionContext) {
|
||||
J.MethodDeclaration m = super.visitMethodDeclaration(method, executionContext);
|
||||
if (m.getLeadingAnnotations().stream().anyMatch(a -> TypeUtils.isOfClassType(a.getType(), "org.springframework.context.annotation.Bean"))) {
|
||||
Object o = getCursor().pollMessage(MSG_KEY);
|
||||
if (o != null && !o.equals(m.getReturnTypeExpression().getType())) {
|
||||
if ((o instanceof JavaType.FullyQualified && m.getReturnTypeExpression().getType() instanceof JavaType.FullyQualified)
|
||||
|| (o instanceof JavaType.Array && m.getReturnTypeExpression().getType() instanceof JavaType.Array)) {
|
||||
m = m.withReturnTypeExpression(m.getReturnTypeExpression().withMarkers(m.getReturnTypeExpression().getMarkers().add(
|
||||
new FixAssistMarker(Tree.randomId()).withScope(m.getId()).withRecipeId(getRecipeId()))));
|
||||
}
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Return visitReturn(Return _return, ExecutionContext executionContext) {
|
||||
Cursor methodCursor = getCursor();
|
||||
if (_return.getExpression() != null) {
|
||||
while (methodCursor != null && !(methodCursor.getValue() instanceof J.Lambda || methodCursor.getValue() instanceof J.MethodDeclaration)) {
|
||||
methodCursor = methodCursor.getParent();
|
||||
}
|
||||
if (methodCursor != null && methodCursor.getValue() instanceof J.MethodDeclaration) {
|
||||
methodCursor.putMessage(MSG_KEY, _return.getExpression().getType());
|
||||
}
|
||||
}
|
||||
return super.visitReturn(_return, executionContext);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(IJavaProject project) {
|
||||
return springBootVersionGreaterOrEqual(3, 0, 0).test(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boot3JavaProblemType getProblemType() {
|
||||
return Boot3JavaProblemType.JAVA_CONCRETE_BEAN_TYPE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,11 +10,11 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.rewrite.reconcile;
|
||||
|
||||
import org.springframework.ide.vscode.boot.java.SpringJavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
|
||||
public interface RecipeSpringJavaProblemDescriptor extends RecipeCodeActionDescriptor {
|
||||
|
||||
SpringJavaProblemType getProblemType();
|
||||
|
||||
ProblemType getProblemType();
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.rewrite.reconcile;
|
||||
|
||||
import org.springframework.ide.vscode.boot.java.SpringJavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeScope;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.UnnecessarySpringExtensionCodeAction;
|
||||
|
||||
@@ -23,8 +23,8 @@ public class UnnecessarySpringExtensionProblem extends UnnecessarySpringExtensio
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpringJavaProblemType getProblemType() {
|
||||
return SpringJavaProblemType.JAVA_TEST_SPRING_EXTENSION;
|
||||
public Boot2JavaProblemType getProblemType() {
|
||||
return Boot2JavaProblemType.JAVA_TEST_SPRING_EXTENSION;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ 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.boot.common.SpringProblemCategories;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
|
||||
@@ -77,4 +78,9 @@ public enum ApplicationPropertiesProblemType implements ProblemType {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemCategory getCategory() {
|
||||
return SpringProblemCategories.PROPERTIES;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ package org.springframework.ide.vscode.boot.yaml.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.ide.vscode.boot.common.SpringProblemCategories;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
|
||||
@@ -80,4 +82,9 @@ public enum ApplicationYamlProblemType implements ProblemType {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemCategory getCategory() {
|
||||
return SpringProblemCategories.YAML;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,176 +1,240 @@
|
||||
{
|
||||
"java": [
|
||||
{
|
||||
"code": "JAVA_SPEL_EXPRESSION_SYNTAX",
|
||||
"label": "SpEL Expression Syntax",
|
||||
"description": "SpEL parser raised a ParseException",
|
||||
"defaultSeverity": "ERROR"
|
||||
[
|
||||
{
|
||||
"id": "boot2",
|
||||
"label": "Boot 2.x Validation",
|
||||
"toggle": {
|
||||
"label": "Enablement",
|
||||
"values": [
|
||||
"AUTO",
|
||||
"OFF",
|
||||
"ON"
|
||||
],
|
||||
"preferenceKey": "boot-java.validation.java.boot2",
|
||||
"defaultValue": "AUTO"
|
||||
},
|
||||
{
|
||||
"code": "JAVA_AUTOWIRED_CONSTRUCTOR",
|
||||
"label": "Unnecessary `@Autowired`",
|
||||
"description": "Unnecessary `@Autowired` over the only constructor",
|
||||
"defaultSeverity": "WARNING"
|
||||
"order": 1,
|
||||
"problemTypes": [
|
||||
{
|
||||
"code": "JAVA_AUTOWIRED_CONSTRUCTOR",
|
||||
"label": "Unnecessary `@Autowired`",
|
||||
"description": "Unnecessary `@Autowired` over the only constructor",
|
||||
"defaultSeverity": "WARNING"
|
||||
},
|
||||
{
|
||||
"code": "JAVA_PUBLIC_BEAN_METHOD",
|
||||
"label": "public `@Bean` method",
|
||||
"description": "Public modifier on `@Bean` method. They no longer have to be public visibility to be usable by Spring.",
|
||||
"defaultSeverity": "HINT"
|
||||
},
|
||||
{
|
||||
"code": "JAVA_TEST_SPRING_EXTENSION",
|
||||
"label": "Unnecessary `@SpringExtension`",
|
||||
"description": "`@SpringBootTest` and all test slice annotations already applies `@SpringExtension` as of Spring Boot 2.1.0.",
|
||||
"defaultSeverity": "WARNING"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "boot3",
|
||||
"label": "Boot 3.x Validation",
|
||||
"toggle": {
|
||||
"label": "Enablement",
|
||||
"values": [
|
||||
"AUTO",
|
||||
"OFF",
|
||||
"ON"
|
||||
],
|
||||
"preferenceKey": "boot-java.validation.java.boot3",
|
||||
"defaultValue": "AUTO"
|
||||
},
|
||||
{
|
||||
"code": "JAVA_PUBLIC_BEAN_METHOD",
|
||||
"label": "public `@Bean` method",
|
||||
"description": "Public modifier on `@Bean` method. They no longer have to be public visibility to be usable by Spring.",
|
||||
"defaultSeverity": "HINT"
|
||||
"order": 2,
|
||||
"problemTypes": [
|
||||
{
|
||||
"code": "JAVA_CONCRETE_BEAN_TYPE",
|
||||
"label": "Not precise bean defintion type",
|
||||
"description": "Bean definition should have precise type for Spring 6 AOT",
|
||||
"defaultSeverity": "WARNING"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "application-properties",
|
||||
"label": "Properties Validation",
|
||||
"order": 3,
|
||||
"problemTypes": [
|
||||
{
|
||||
"code": "PROP_INVALID_BEAN_NAVIGATION",
|
||||
"label": "Invalid bean navigation",
|
||||
"description": "Accessing a 'bean property' in a type that doesn't 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't support that",
|
||||
"defaultSeverity": "ERROR"
|
||||
},
|
||||
{
|
||||
"code": "PROP_EXPECTED_DOT_OR_LBRACK",
|
||||
"label": "Expected dot or lbrack",
|
||||
"description": "Unexpected character found where a '.' or '[' was expected",
|
||||
"defaultSeverity": "ERROR"
|
||||
},
|
||||
{
|
||||
"code": "PROP_NO_MATCHING_RBRACK",
|
||||
"label": "No matching rbrack",
|
||||
"description": "Found a '[' but no matching ']'",
|
||||
"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't parse as such",
|
||||
"defaultSeverity": "ERROR"
|
||||
},
|
||||
{
|
||||
"code": "PROP_INVALID_BEAN_PROPERTY",
|
||||
"label": "Invalid bean property",
|
||||
"description": "Accessing a named property in a type that doesn't 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's 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"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "application-yaml",
|
||||
"label": "YAML Properties Validation",
|
||||
"order": 4,
|
||||
"problemTypes": [
|
||||
{
|
||||
"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's classpath",
|
||||
"defaultSeverity": "WARNING"
|
||||
},
|
||||
{
|
||||
"code": "YAML_VALUE_TYPE_MISMATCH",
|
||||
"label": "Value type mismatch",
|
||||
"description": "Expecting a value of a certain type, but value doesn't parse as such",
|
||||
"defaultSeverity": "ERROR"
|
||||
},
|
||||
{
|
||||
"code": "YAML_EXPECT_SCALAR",
|
||||
"label": "Expect scalar",
|
||||
"description": "Expecting a 'scalar' value but found something more complex.",
|
||||
"defaultSeverity": "ERROR"
|
||||
},
|
||||
{
|
||||
"code": "YAML_EXPECT_TYPE_FOUND_SEQUENCE",
|
||||
"label": "Expect type found sequence",
|
||||
"description": "Found a 'sequence' node where a non 'list-like' type is expected",
|
||||
"defaultSeverity": "ERROR"
|
||||
},
|
||||
{
|
||||
"code": "YAML_EXPECT_TYPE_FOUND_MAPPING",
|
||||
"label": "Expect type found mapping",
|
||||
"description": "Found a 'mapping' node where a type that can't be treated as a 'property map' is expected",
|
||||
"defaultSeverity": "ERROR"
|
||||
},
|
||||
{
|
||||
"code": "YAML_EXPECT_MAPPING",
|
||||
"label": "Expect mapping",
|
||||
"description": "Expecting a 'mapping' node but found something else",
|
||||
"defaultSeverity": "ERROR"
|
||||
},
|
||||
{
|
||||
"code": "YAML_EXPECT_BEAN_PROPERTY_NAME",
|
||||
"label": "Expect bean property name",
|
||||
"description": "Expecting a 'bean property' 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't 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 '[]'",
|
||||
"defaultSeverity": "WARNING"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "spel",
|
||||
"label": "SPEL Validation",
|
||||
"toggle": {
|
||||
"label": "Enablement",
|
||||
"values": [
|
||||
"OFF",
|
||||
"ON"
|
||||
],
|
||||
"preferenceKey": "boot-java.validation.spel.on",
|
||||
"defaultValue": "ON"
|
||||
},
|
||||
{
|
||||
"code": "JAVA_TEST_SPRING_EXTENSION",
|
||||
"label": "Unnecessary `@SpringExtension`",
|
||||
"description": "`@SpringBootTest` and all test slice annotations already applies `@SpringExtension` as of Spring Boot 2.1.0.",
|
||||
"defaultSeverity": "WARNING"
|
||||
}
|
||||
],
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
"order": 5,
|
||||
"problemTypes": [
|
||||
{
|
||||
"code": "JAVA_SPEL_EXPRESSION_SYNTAX",
|
||||
"label": "SpEL Expression Syntax",
|
||||
"description": "SpEL parser raised a ParseException",
|
||||
"defaultSeverity": "ERROR"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -11,7 +11,9 @@
|
||||
package org.springframework.ide.vscode.boot.test;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ide.vscode.boot.java.SpringJavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.Boot3JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.SpelProblemType;
|
||||
import org.springframework.ide.vscode.boot.properties.reconcile.ApplicationPropertiesProblemType;
|
||||
import org.springframework.ide.vscode.boot.yaml.reconcile.ApplicationYamlProblemType;
|
||||
|
||||
@@ -25,7 +27,9 @@ public class ProblemTypesMetadataTest {
|
||||
ProblemTypesToJson reader = new ProblemTypesToJson().read();
|
||||
reader.validate("application-properties", ApplicationPropertiesProblemType.values());
|
||||
reader.validate("application-yaml", ApplicationYamlProblemType.values());
|
||||
reader.validate("java", SpringJavaProblemType.values());
|
||||
reader.validate("boot2", Boot2JavaProblemType.values());
|
||||
reader.validate("boot3", Boot3JavaProblemType.values());
|
||||
reader.validate("spel", SpelProblemType.values());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2020 Pivotal, Inc.
|
||||
* Copyright (c) 2020, 2022 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
|
||||
@@ -17,19 +17,26 @@ import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
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.java.SpringJavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.Boot3JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.SpelProblemType;
|
||||
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.ProblemCategory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory.Toggle;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
import org.springframework.ide.vscode.commons.util.Streams;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
|
||||
import org.springframework.ide.vscode.commons.yaml.util.JSONCursor;
|
||||
|
||||
@@ -58,6 +65,7 @@ public class ProblemTypesToJson {
|
||||
public static final String packageJsonPath = "../../vscode-extensions/vscode-spring-boot/package.json";
|
||||
public static final String resourcesPath = "src/main/resources";
|
||||
public static final String metaDataFileName = "problem-types.json";
|
||||
public static final String problemCategoriesFileName = "problem-categories.json";
|
||||
|
||||
public static class ProblemTypeData {
|
||||
String code;
|
||||
@@ -70,7 +78,7 @@ public class ProblemTypesToJson {
|
||||
public ProblemTypeData(ProblemType type) {
|
||||
this.code = type.getCode();
|
||||
this.description = type.getDescription();
|
||||
this.defaultSeverity =type.getDefaultSeverity().toString();
|
||||
this.defaultSeverity =type.getDefaultSeverity().name();
|
||||
this.label = type.getLabel();
|
||||
}
|
||||
|
||||
@@ -108,46 +116,106 @@ public class ProblemTypesToJson {
|
||||
this.label = label;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ProblemCategoryData implements Comparable<ProblemCategoryData> {
|
||||
private String id;
|
||||
private String label;
|
||||
private Toggle toggle;
|
||||
private int order;
|
||||
private List<ProblemTypeData> problemTypes;
|
||||
|
||||
ProblemCategoryData(ProblemCategory category, Collection<ProblemType> problemTypes) {
|
||||
this.id = category.getId();
|
||||
this.label = category.getLabel();
|
||||
this.toggle = category.getToggle();
|
||||
this.order = category.order;
|
||||
this.problemTypes = problemTypes.stream().map(ProblemTypeData::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
ProblemCategoryData(ProblemCategory category) {
|
||||
this(category, Collections.emptyList());
|
||||
}
|
||||
|
||||
Map<String, ProblemTypeData[]> problemTypes = new HashMap<>();
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public Toggle getToggle() {
|
||||
return toggle;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public List<ProblemTypeData> getProblemTypes() {
|
||||
return problemTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ProblemCategoryData o) {
|
||||
return getOrder() - o.getOrder();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private List<ProblemCategoryData> problemCategories = new ArrayList<>();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ProblemTypesToJson writer = new ProblemTypesToJson();
|
||||
writer.problemsFor("application-yaml", ApplicationYamlProblemType.values());
|
||||
writer.problemsFor("application-properties", ApplicationPropertiesProblemType.values());
|
||||
writer.problemsFor("java", SpringJavaProblemType.values());
|
||||
writer.dump();
|
||||
|
||||
writer.collectProblemTypeData(SpelProblemType.values());
|
||||
writer.collectProblemTypeData(ApplicationYamlProblemType.values());
|
||||
writer.collectProblemTypeData(Boot2JavaProblemType.values());
|
||||
writer.collectProblemTypeData(ApplicationPropertiesProblemType.values());
|
||||
writer.collectProblemTypeData(Boot3JavaProblemType.values());
|
||||
|
||||
Collections.sort(writer.problemCategories);
|
||||
|
||||
writer.dump();
|
||||
|
||||
writer.updatePackageJson(new File(packageJsonPath), "spring-boot.ls.problem");
|
||||
}
|
||||
|
||||
private void dump() throws IOException {
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
String json = gson.toJson(problemTypes);
|
||||
FileUtils.writeStringToFile(new File(resourcesPath+"/"+metaDataFileName), json);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||
String json = gson.toJson(problemCategories);
|
||||
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]);
|
||||
|
||||
private void collectProblemTypeData(ProblemType[] problems) {
|
||||
for (int i = 0; i < problems.length; i++) {
|
||||
ProblemCategory category = problems[i].getCategory();
|
||||
if (category != null) {
|
||||
ProblemCategoryData categoryData = problemCategories.stream().filter(c -> c.getId().equals(category.getId())).findFirst().orElseGet(() -> {
|
||||
ProblemCategoryData d = new ProblemCategoryData(category);
|
||||
problemCategories.add(d);
|
||||
return d;
|
||||
});
|
||||
categoryData.getProblemTypes().add(new ProblemTypeData(problems[i]));
|
||||
} else {
|
||||
throw new IllegalStateException("No category for problem " + problems[i].getCode());
|
||||
}
|
||||
}
|
||||
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());
|
||||
TypeToken<List<ProblemCategoryData>> tt = new TypeToken<List<ProblemCategoryData>>() {};
|
||||
problemCategories = 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());
|
||||
List<ProblemTypeData> metadataProblemTypes = problemCategories.stream().filter(c -> c.getId().equals(name)).findFirst().map(c -> c.getProblemTypes()).orElse(Collections.emptyList());
|
||||
Set<String> metadataHas = metadataProblemTypes.stream().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)) {
|
||||
@@ -160,8 +228,8 @@ public class ProblemTypesToJson {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < metadataProblemTypes.length; i++) {
|
||||
ProblemTypeData metadata = metadataProblemTypes[i];
|
||||
for (int i = 0; i < metadataProblemTypes.size(); i++) {
|
||||
ProblemTypeData metadata = metadataProblemTypes.get(i);
|
||||
ProblemType actual = actualProblemTypes[i];
|
||||
assertEquals(actual.getCode(), metadata.getCode());
|
||||
assertEquals(actual.getDescription(), metadata.getDescription());
|
||||
@@ -170,33 +238,99 @@ public class ProblemTypesToJson {
|
||||
}
|
||||
}
|
||||
|
||||
public void updatePackageJson(File packageJsonFile, String propertyPrefix) throws Exception {
|
||||
public void updatePackageJson(File packageJsonFile, String propertyPrefix, String id, ProblemType[] problemTypes) throws Exception {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.serializeNulls()
|
||||
.create();
|
||||
JsonElement parsed = gson.fromJson(new FileReader(packageJsonFile), JsonElement.class);
|
||||
JsonObject configProps = (JsonObject) YamlPath.fromProperty("contributes.configuration.properties").traverse(new JSONCursor(parsed)).target;
|
||||
Set<String> removeProps = configProps.keySet().stream().filter(s -> s.startsWith(propertyPrefix)).collect(Collectors.toSet());
|
||||
for (String rp : removeProps) {
|
||||
configProps.remove(rp);
|
||||
}
|
||||
JsonArray severities = new JsonArray();
|
||||
for (ProblemSeverity severity : ProblemSeverity.values()) {
|
||||
severities.add(severity.name());
|
||||
}
|
||||
for (Entry<String, ProblemTypeData[]> e : problemTypes.entrySet()) {
|
||||
String editorType = e.getKey();
|
||||
for (ProblemTypeData data : e.getValue()) {
|
||||
JsonArray allProps = (JsonArray) YamlPath.fromProperty("contributes.configuration.properties").traverse(new JSONCursor(parsed)).target;
|
||||
JsonObject configProps = Streams.fromIterable(allProps).filter(JsonObject.class::isInstance).map(JsonObject.class::cast).filter(o -> {
|
||||
JsonElement element = o.get("id");
|
||||
return element != null && id.equals(element.getAsString());
|
||||
}).findFirst().orElse(null);
|
||||
if (configProps != null) {
|
||||
Set<String> removeProps = configProps.keySet().stream().filter(s -> s.startsWith(propertyPrefix)).collect(Collectors.toSet());
|
||||
for (String rp : removeProps) {
|
||||
configProps.remove(rp);
|
||||
}
|
||||
JsonArray severities = new JsonArray();
|
||||
for (ProblemSeverity severity : ProblemSeverity.values()) {
|
||||
severities.add(severity.name());
|
||||
}
|
||||
for (ProblemType problemType : problemTypes) {
|
||||
ProblemTypeData data = new ProblemTypeData(problemType);
|
||||
JsonObject schema = new JsonObject();
|
||||
schema.addProperty("type", "string");
|
||||
schema.addProperty("default", data.defaultSeverity);
|
||||
schema.addProperty("description", data.description);
|
||||
schema.add("enum", severities);
|
||||
configProps.add(propertyPrefix+"."+editorType+"."+data.code, schema);
|
||||
configProps.add(propertyPrefix + "." + id + "." + data.code, schema);
|
||||
}
|
||||
|
||||
String newContent = gson.toJson(parsed);
|
||||
FileUtils.writeStringToFile(packageJsonFile, newContent);
|
||||
} else {
|
||||
throw new IllegalStateException("Cannot find config object with 'id' property equal to '" + id + "'");
|
||||
}
|
||||
}
|
||||
|
||||
public void updatePackageJson(File packageJsonFile, String propertyPrefix) throws Exception {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.disableHtmlEscaping()
|
||||
.serializeNulls()
|
||||
.create();
|
||||
JsonElement parsed = gson.fromJson(new FileReader(packageJsonFile), JsonElement.class);
|
||||
JsonArray allProps = (JsonArray) YamlPath.fromProperty("contributes.configuration").traverse(new JSONCursor(parsed)).target;
|
||||
|
||||
JsonArray severities = new JsonArray();
|
||||
for (ProblemSeverity severity : ProblemSeverity.values()) {
|
||||
severities.add(severity.name());
|
||||
}
|
||||
|
||||
for (ProblemCategoryData category : problemCategories) {
|
||||
JsonObject configProps = Streams.fromIterable(allProps).filter(JsonObject.class::isInstance).map(JsonObject.class::cast).filter(o -> {
|
||||
JsonElement element = o.get("id");
|
||||
return element != null && category.getId().equals(element.getAsString());
|
||||
}).findFirst().orElse(null);
|
||||
|
||||
if (configProps != null) {
|
||||
allProps.remove(configProps);
|
||||
}
|
||||
}
|
||||
|
||||
for (ProblemCategoryData category : problemCategories) {
|
||||
JsonObject configProps = new JsonObject();
|
||||
configProps.addProperty("id", category.getId());
|
||||
configProps.addProperty("title", category.getLabel());
|
||||
configProps.addProperty("order", 400 + category.order);
|
||||
JsonObject props = new JsonObject();
|
||||
if (category.getToggle() != null) {
|
||||
Toggle categorySwitch = category.getToggle();
|
||||
JsonObject switchObj = new JsonObject();
|
||||
switchObj.addProperty("type", "string");
|
||||
switchObj.addProperty("default", categorySwitch.getDefaultValue().name());
|
||||
switchObj.addProperty("description", categorySwitch.getLabel());
|
||||
JsonArray vals = new JsonArray();
|
||||
for (Toggle.Option s : categorySwitch.getValues()) {
|
||||
vals.add(s.name());
|
||||
}
|
||||
switchObj.add("enum", vals);
|
||||
props.add(categorySwitch.getPreferenceKey(), switchObj);
|
||||
}
|
||||
for (ProblemTypeData data : category.getProblemTypes()) {
|
||||
JsonObject schema = new JsonObject();
|
||||
schema.addProperty("type", "string");
|
||||
schema.addProperty("default", data.defaultSeverity);
|
||||
schema.addProperty("description", data.description);
|
||||
schema.add("enum", severities);
|
||||
props.add(propertyPrefix + "." + category.getId() + "." + data.code, schema);
|
||||
}
|
||||
configProps.add("properties", props);
|
||||
allProps.add(configProps);
|
||||
}
|
||||
|
||||
String newContent = gson.toJson(parsed);
|
||||
FileUtils.writeStringToFile(packageJsonFile, newContent);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user