Deprecated properties without replacement ...

Should not get a "Replace with..." quickfix
This commit is contained in:
Kris De Volder
2019-02-06 12:57:57 -08:00
parent 1106709183
commit bc8b0300ca
10 changed files with 137 additions and 13 deletions

View File

@@ -858,6 +858,18 @@ public class Editor {
return actions.get(0);
}
public void assertNoCodeAction(Diagnostic problem) throws Exception {
List<CodeAction> actions = getCodeActions(problem);
if (actions!=null && !actions.isEmpty()) {
StringBuilder found = new StringBuilder();
for (CodeAction codeAction : actions) {
found.append("\n"+codeAction.getLabel());
}
fail("Expected no code actions but found:"+found);
}
}
public String getUri() {
return doc.getUri();
}
@@ -896,4 +908,5 @@ public class Editor {
public void setCursor(Position position) {
this.selectionStart = this.selectionEnd = doc.toOffset(position);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,13 +28,30 @@ import java.io.Serializable;
@SuppressWarnings("serial")
public class Deprecation implements Serializable {
private Level level = Level.WARNING;
private String reason;
private String shortReason;
private String replacement;
/**
* Define the {@link Level} of deprecation.
* @return the deprecation level
*/
public Level getLevel() {
return this.level;
}
public void setLevel(Level level) {
this.level = level;
}
/**
* A reason why the related property is deprecated, if any. Can be multi-lines.
* @return the deprecation reason
* @see #getShortReason()
*/
public String getReason() {
return this.reason;
@@ -44,6 +61,20 @@ public class Deprecation implements Serializable {
this.reason = reason;
}
/**
* A single-line, single-sentence reason why the related property is deprecated, if
* any.
* @return the short deprecation reason
* @see #getReason()
*/
public String getShortReason() {
return this.shortReason;
}
public void setShortReason(String shortReason) {
this.shortReason = shortReason;
}
/**
* The full name of the property that replaces the related deprecated property, if
* any.
@@ -59,8 +90,24 @@ public class Deprecation implements Serializable {
@Override
public String toString() {
return "Deprecation{" + "reason='" + this.reason + '\'' + ", replacement='"
+ this.replacement + '\'' + '}';
return "Deprecation{" + "level='" + this.level + '\'' + ", reason='" + this.reason
+ '\'' + ", replacement='" + this.replacement + '\'' + '}';
}
}
/**
* Define the deprecation level.
*/
public enum Level {
/**
* The property is still bound.
*/
WARNING,
/**
* The property has been removed and is no longer bound.
*/
ERROR
}
}

View File

@@ -17,6 +17,7 @@ import java.util.List;
import org.springframework.ide.vscode.boot.configurationmetadata.ConfigurationMetadataProperty;
import org.springframework.ide.vscode.boot.configurationmetadata.ConfigurationMetadataSource;
import org.springframework.ide.vscode.boot.configurationmetadata.Deprecation;
import org.springframework.ide.vscode.boot.configurationmetadata.Deprecation.Level;
import org.springframework.ide.vscode.boot.configurationmetadata.ValueHint;
import org.springframework.ide.vscode.boot.configurationmetadata.ValueProvider;
import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry.ValueProviderStrategy;
@@ -207,6 +208,11 @@ public class PropertyInfo {
return deprecation == null ? null : deprecation.getReplacement();
}
public Level getDeprecationLevel() {
return deprecation == null ? null : deprecation.getLevel();
}
public void addValueHints(List<ValueHint> hints) {
Builder<ValueHint> builder = ImmutableList.builder();
builder.addAll(valueHints);

View File

@@ -12,6 +12,7 @@
package org.springframework.ide.vscode.boot.metadata.types;
import org.springframework.ide.vscode.boot.configurationmetadata.Deprecation;
import org.springframework.ide.vscode.boot.configurationmetadata.Deprecation.Level;
import org.springframework.ide.vscode.commons.util.Renderable;
import org.springframework.ide.vscode.commons.util.Renderables;
import org.springframework.ide.vscode.commons.yaml.schema.YTypedProperty;
@@ -51,10 +52,12 @@ public class TypedProperty implements YTypedProperty {
this.deprecation = deprecation;
}
@Override
public String getName() {
return name;
}
@Override
public Type getType() {
return type;
}
@@ -82,6 +85,7 @@ public class TypedProperty implements YTypedProperty {
return null;
}
@Override
public boolean isDeprecated() {
return deprecation!=null;
}
@@ -100,8 +104,12 @@ public class TypedProperty implements YTypedProperty {
return null;
}
public Level getDeprecationLevel() {
return deprecation == null ? null : deprecation.getLevel();
}
public Deprecation getDeprecation() {
return deprecation;
}
}

View File

@@ -11,7 +11,7 @@
package org.springframework.ide.vscode.boot.yaml.reconcile;
import static org.springframework.ide.vscode.boot.yaml.reconcile.ApplicationYamlProblemType.YAML_DEPRECATED;
import static org.springframework.ide.vscode.boot.yaml.reconcile.ApplicationYamlProblemType.*;
import static org.springframework.ide.vscode.boot.yaml.reconcile.ApplicationYamlProblemType.YAML_DUPLICATE_KEY;
import static org.springframework.ide.vscode.commons.yaml.ast.NodeUtil.asScalar;
import static org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST.getChildren;
@@ -25,6 +25,7 @@ import java.util.regex.Pattern;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.springframework.ide.vscode.boot.configurationmetadata.Deprecation.Level;
import org.springframework.ide.vscode.boot.metadata.IndexNavigator;
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
import org.springframework.ide.vscode.boot.metadata.types.Type;
@@ -389,7 +390,7 @@ public class ApplicationYamlASTReconciler implements YamlASTReconciler {
private void deprecatedProperty(String docUri, PropertyInfo property, Node keyNode, QuickfixType fixType) {
SpringPropertyProblem problem = deprecatedPropertyProblem(docUri, property.getId(), null, keyNode,
property.getDeprecationReplacement(), property.getDeprecationReason(), fixType);
property.getDeprecationReplacement(), property.getDeprecationReason(), property.getDeprecationLevel(), fixType);
problem.setMetadata(property);
//problem.setProblemFixer(ReplaceDeprecatedYamlQuickfix.FIXER);
problems.accept(problem);
@@ -397,18 +398,20 @@ public class ApplicationYamlASTReconciler implements YamlASTReconciler {
private void deprecatedProperty(String docUri, Type contextType, TypedProperty property, Node keyNode, QuickfixType fixType) {
SpringPropertyProblem problem = deprecatedPropertyProblem(docUri, property.getName(), typeUtil.niceTypeName(contextType),
keyNode, property.getDeprecationReplacement(), property.getDeprecationReason(), fixType);
keyNode, property.getDeprecationReplacement(), property.getDeprecationReason(), property.getDeprecationLevel(), fixType);
problems.accept(problem);
}
protected SpringPropertyProblem deprecatedPropertyProblem(String docUri, String name, String contextType, Node keyNode,
String replace, String reason, QuickfixType fixType) {
SpringPropertyProblem problem = problem(YAML_DEPRECATED, keyNode, TypeUtil.deprecatedPropertyMessage(name, contextType, replace, reason));
String replace, String reason, Level level, QuickfixType fixType) {
ApplicationYamlProblemType problemType = level==Level.ERROR ? YAML_DEPRECATED_ERROR : YAML_DEPRECATED_WARNING;
SpringPropertyProblem problem = problem(problemType, keyNode, TypeUtil.deprecatedPropertyMessage(name, contextType, replace, reason));
problem.setPropertyName(name);
Range range = new Range(new Position(keyNode.getStartMark().getLine(), keyNode.getStartMark().getColumn()),
new Position(keyNode.getEndMark().getLine(), keyNode.getEndMark().getColumn()));
problem.addQuickfix(new QuickfixData<>(fixType, new DeprecatedPropertyData(docUri, range, replace), "Replace with `" + replace + "`"));
if (StringUtil.hasText(replace)) {
problem.addQuickfix(new QuickfixData<>(fixType, new DeprecatedPropertyData(docUri, range, replace), "Replace with `" + replace + "`"));
}
return problem;
}

View File

@@ -30,7 +30,8 @@ public enum ApplicationYamlProblemType implements ProblemType {
YAML_EXPECT_MAPPING("Expecting a 'mapping' node but found something else"),
YAML_EXPECT_BEAN_PROPERTY_NAME("Expecting a 'bean property' name but found something more complex"),
YAML_INVALID_BEAN_PROPERTY("Accessing a named property in a type that doesn't provide a property accessor with that name"),
YAML_DEPRECATED(WARNING, "Property is marked as Deprecated"),
YAML_DEPRECATED_ERROR(ERROR, "Property is marked as Deprecated(Error)"),
YAML_DEPRECATED_WARNING(WARNING, "Property is marked as Deprecated(Warning)"),
YAML_DUPLICATE_KEY("A mapping node contains multiple entries for the same key");
private final ProblemSeverity defaultSeverity;
@@ -51,6 +52,7 @@ public enum ApplicationYamlProblemType implements ProblemType {
this(ERROR, description);
}
@Override
public ProblemSeverity getDefaultSeverity() {
return defaultSeverity;
}

View File

@@ -36,4 +36,9 @@ public class SpringPropertyProblem extends ReconcileProblemImpl {
propertyName = name;
}
@Override
public String toString() {
return "SpringPropertyProblem("+propertyName+", "+this.getMessage()+")";
}
}

View File

@@ -28,6 +28,7 @@ import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.junit.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ide.vscode.boot.app.BootLanguageServerInitializer;
import org.springframework.ide.vscode.boot.configurationmetadata.Deprecation.Level;
import org.springframework.ide.vscode.boot.editor.harness.PropertyIndexHarness.ItemConfigurer;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.commons.java.IJavaProject;
@@ -259,6 +260,10 @@ public abstract class AbstractPropsEditorTest {
}
}
public void deprecate(String key, String replacedBy, String reason, Level level) {
md.deprecate(key, replacedBy, reason, level);
}
public void deprecate(String key, String replacedBy, String reason) {
md.deprecate(key, replacedBy, reason);
}

View File

@@ -21,6 +21,7 @@ import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.gradle.internal.impldep.com.google.common.collect.ImmutableList;
import org.springframework.ide.vscode.boot.configurationmetadata.ConfigurationMetadataProperty;
import org.springframework.ide.vscode.boot.configurationmetadata.Deprecation;
import org.springframework.ide.vscode.boot.configurationmetadata.Deprecation.Level;
import org.springframework.ide.vscode.boot.configurationmetadata.ValueHint;
import org.springframework.ide.vscode.boot.configurationmetadata.ValueProvider;
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
@@ -147,6 +148,16 @@ public class PropertyIndexHarness {
}
}
public synchronized void deprecate(String key, String replacedBy, String reason, Level level) {
index = null;
ConfigurationMetadataProperty info = datas.get(key);
Deprecation d = new Deprecation();
d.setReplacement(replacedBy);
d.setReason(reason);
d.setLevel(level);
info.setDeprecation(d);
}
public synchronized void deprecate(String key, String replacedBy, String reason) {
index = null;
ConfigurationMetadataProperty info = datas.get(key);

View File

@@ -21,6 +21,7 @@ import java.time.Duration;
import java.util.Optional;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -30,6 +31,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
import org.springframework.ide.vscode.boot.bootiful.PropertyEditorTestConf;
import org.springframework.ide.vscode.boot.configurationmetadata.Deprecation.Level;
import org.springframework.ide.vscode.boot.editor.harness.AbstractPropsEditorTest;
import org.springframework.ide.vscode.boot.metadata.CachingValueProvider;
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
@@ -4015,6 +4017,28 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
editor.assertContextualCompletions("B<*>", "BLUE<*>");
}
@Test public void test_NoQuickfixForDeprecatedProperty() throws Exception {
//See: https://www.pivotaltracker.com/story/show/163720976
//Summary: if a deprecated property metadata does *not*
// provide a 'replace with' hint then it should not create
// a 'Replace with' quickfix.
data("spring.devtools.remote.debug.local-port", "java.lang.Integer",
8000, "Local remote debug server port."
);
deprecate("spring.devtools.remote.debug.local-port", null, "No longer supported", Level.ERROR);
Editor editor = harness.newEditor(
"spring:\n" +
" devtools:\n" +
" remote:\n" +
" debug:\n" +
" local-port: 8888"
);
Diagnostic problem = editor.assertProblems("local-port|Deprecated").get(0);
editor.assertNoCodeAction(problem);
assertEquals(DiagnosticSeverity.Error, problem.getSeverity());
}
///////////////// cruft ////////////////////////////////////////////////////////