improved value content assist to work with member value pairs and refactored code to reduce code duplications
This commit is contained in:
@@ -17,11 +17,13 @@ import java.util.List;
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MemberValuePair;
|
||||
import org.eclipse.jdt.core.dom.SimpleName;
|
||||
import org.eclipse.jdt.core.dom.StringLiteral;
|
||||
import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.util.FuzzyMap;
|
||||
import org.springframework.ide.vscode.commons.util.FuzzyMap.Match;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
@@ -56,61 +58,24 @@ public class ValueCompletionProcessor {
|
||||
}
|
||||
// case: @Value(prefix<*>)
|
||||
else if (node instanceof SimpleName && node.getParent() instanceof Annotation) {
|
||||
String prefix = identifyPropertyPrefix(node.toString(), offset - node.getStartPosition());
|
||||
|
||||
int startOffset = node.getStartPosition();
|
||||
int endOffset = node.getStartPosition() + node.getLength();
|
||||
|
||||
String proposalPrefix = "\"";
|
||||
String proposalPostfix = "\"";
|
||||
|
||||
List<Match<ConfigurationMetadataProperty>> matches = findMatches(prefix);
|
||||
|
||||
for (Match<ConfigurationMetadataProperty> match : matches) {
|
||||
|
||||
DocumentEdits edits = new DocumentEdits(doc);
|
||||
edits.replace(startOffset, endOffset, proposalPrefix + "${" + match.data.getId() + "}" + proposalPostfix);
|
||||
|
||||
ValuePropertyKeyProposal proposal = new ValuePropertyKeyProposal(edits, match.data.getId(), match.data.getName(), null);
|
||||
completions.add(proposal);
|
||||
}
|
||||
computeProposalsForSimpleName(node, completions, offset, doc);
|
||||
}
|
||||
// case: @Value(value=<*>)
|
||||
else if (node instanceof SimpleName && node.getParent() instanceof MemberValuePair
|
||||
&& "value".equals(((MemberValuePair)node.getParent()).getName().toString())) {
|
||||
computeProposalsForSimpleName(node, completions, offset, doc);
|
||||
}
|
||||
// case: @Value("prefix<*>")
|
||||
else if (node instanceof StringLiteral && node.getParent() instanceof Annotation) {
|
||||
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
|
||||
|
||||
String prefix = identifyPropertyPrefix(doc.get(node.getStartPosition() + 1, offset - (node.getStartPosition() + 1)), offset - (node.getStartPosition() + 1));
|
||||
|
||||
int startOffset = offset - prefix.length();
|
||||
int endOffset = offset;
|
||||
|
||||
|
||||
String prePrefix = doc.get(node.getStartPosition() + 1, offset - prefix.length() - node.getStartPosition() - 1);
|
||||
|
||||
String preCompletion;
|
||||
if (prePrefix.endsWith("${")) {
|
||||
preCompletion = "";
|
||||
}
|
||||
else if (prePrefix.endsWith("$")) {
|
||||
preCompletion = "{";
|
||||
}
|
||||
else {
|
||||
preCompletion = "${";
|
||||
}
|
||||
|
||||
String fullNodeContent = doc.get(node.getStartPosition(), node.getLength());
|
||||
String postCompletion = isClosingBracketMissing(fullNodeContent + preCompletion) ? "}" : "";
|
||||
|
||||
List<Match<ConfigurationMetadataProperty>> matches = findMatches(prefix);
|
||||
|
||||
for (Match<ConfigurationMetadataProperty> match : matches) {
|
||||
|
||||
DocumentEdits edits = new DocumentEdits(doc);
|
||||
edits.replace(startOffset, endOffset, preCompletion + match.data.getId() + postCompletion);
|
||||
|
||||
ValuePropertyKeyProposal proposal = new ValuePropertyKeyProposal(edits, match.data.getId(), match.data.getName(), null);
|
||||
completions.add(proposal);
|
||||
}
|
||||
computeProposalsForStringLiteral(node, completions, offset, doc);
|
||||
}
|
||||
}
|
||||
// case: @Value(value="prefix<*>")
|
||||
else if (node instanceof StringLiteral && node.getParent() instanceof MemberValuePair
|
||||
&& "value".equals(((MemberValuePair)node.getParent()).getName().toString())) {
|
||||
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
|
||||
computeProposalsForStringLiteral(node, completions, offset, doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,6 +83,63 @@ public class ValueCompletionProcessor {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void computeProposalsForSimpleName(ASTNode node, List<ICompletionProposal> completions, int offset,
|
||||
IDocument doc) {
|
||||
String prefix = identifyPropertyPrefix(node.toString(), offset - node.getStartPosition());
|
||||
|
||||
int startOffset = node.getStartPosition();
|
||||
int endOffset = node.getStartPosition() + node.getLength();
|
||||
|
||||
String proposalPrefix = "\"";
|
||||
String proposalPostfix = "\"";
|
||||
|
||||
List<Match<ConfigurationMetadataProperty>> matches = findMatches(prefix);
|
||||
|
||||
for (Match<ConfigurationMetadataProperty> match : matches) {
|
||||
|
||||
DocumentEdits edits = new DocumentEdits(doc);
|
||||
edits.replace(startOffset, endOffset, proposalPrefix + "${" + match.data.getId() + "}" + proposalPostfix);
|
||||
|
||||
ValuePropertyKeyProposal proposal = new ValuePropertyKeyProposal(edits, match.data.getId(), match.data.getName(), null);
|
||||
completions.add(proposal);
|
||||
}
|
||||
}
|
||||
|
||||
private void computeProposalsForStringLiteral(ASTNode node, List<ICompletionProposal> completions, int offset,
|
||||
IDocument doc) throws BadLocationException {
|
||||
String prefix = identifyPropertyPrefix(doc.get(node.getStartPosition() + 1, offset - (node.getStartPosition() + 1)), offset - (node.getStartPosition() + 1));
|
||||
|
||||
int startOffset = offset - prefix.length();
|
||||
int endOffset = offset;
|
||||
|
||||
String prePrefix = doc.get(node.getStartPosition() + 1, offset - prefix.length() - node.getStartPosition() - 1);
|
||||
|
||||
String preCompletion;
|
||||
if (prePrefix.endsWith("${")) {
|
||||
preCompletion = "";
|
||||
}
|
||||
else if (prePrefix.endsWith("$")) {
|
||||
preCompletion = "{";
|
||||
}
|
||||
else {
|
||||
preCompletion = "${";
|
||||
}
|
||||
|
||||
String fullNodeContent = doc.get(node.getStartPosition(), node.getLength());
|
||||
String postCompletion = isClosingBracketMissing(fullNodeContent + preCompletion) ? "}" : "";
|
||||
|
||||
List<Match<ConfigurationMetadataProperty>> matches = findMatches(prefix);
|
||||
|
||||
for (Match<ConfigurationMetadataProperty> match : matches) {
|
||||
|
||||
DocumentEdits edits = new DocumentEdits(doc);
|
||||
edits.replace(startOffset, endOffset, preCompletion + match.data.getId() + postCompletion);
|
||||
|
||||
ValuePropertyKeyProposal proposal = new ValuePropertyKeyProposal(edits, match.data.getId(), match.data.getName(), null);
|
||||
completions.add(proposal);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isClosingBracketMissing(String fullNodeContent) {
|
||||
int bracketOpens = 0;
|
||||
|
||||
@@ -95,6 +95,24 @@ public class ValueCompletionTest {
|
||||
"@Value(\"${spring.prop1}\"<*>)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyBracketsCompletionWithParamName() throws Exception {
|
||||
prepareCase("@Value(\"onField\")", "@Value(value=<*>)");
|
||||
prepareDefaultIndexData();
|
||||
|
||||
assertAnnotationCompletions(
|
||||
"@Value(value=\"${data.prop2}\"<*>)",
|
||||
"@Value(value=\"${else.prop3}\"<*>)",
|
||||
"@Value(value=\"${spring.prop1}\"<*>)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyBracketsCompletionWithWrongParamName() throws Exception {
|
||||
prepareCase("@Value(\"onField\")", "@Value(another=<*>)");
|
||||
prepareDefaultIndexData();
|
||||
assertAnnotationCompletions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyDollarNoQoutesCompletion() throws Exception {
|
||||
prepareCase("@Value(\"onField\")", "@Value($<*>)");
|
||||
@@ -106,6 +124,17 @@ public class ValueCompletionTest {
|
||||
"@Value(\"${spring.prop1}\"<*>)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyDollarNoQoutesWithParamCompletion() throws Exception {
|
||||
prepareCase("@Value(\"onField\")", "@Value(value=$<*>)");
|
||||
prepareDefaultIndexData();
|
||||
|
||||
assertAnnotationCompletions(
|
||||
"@Value(value=\"${data.prop2}\"<*>)",
|
||||
"@Value(value=\"${else.prop3}\"<*>)",
|
||||
"@Value(value=\"${spring.prop1}\"<*>)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyDollarCompletion() throws Exception {
|
||||
prepareCase("@Value(\"onField\")", "@Value(\"$<*>\")");
|
||||
@@ -117,6 +146,17 @@ public class ValueCompletionTest {
|
||||
"@Value(\"${spring.prop1}<*>\")");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyDollarWithParamCompletion() throws Exception {
|
||||
prepareCase("@Value(\"onField\")", "@Value(value=\"$<*>\")");
|
||||
prepareDefaultIndexData();
|
||||
|
||||
assertAnnotationCompletions(
|
||||
"@Value(value=\"${data.prop2}<*>\")",
|
||||
"@Value(value=\"${else.prop3}<*>\")",
|
||||
"@Value(value=\"${spring.prop1}<*>\")");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDollarWithBracketsCompletion() throws Exception {
|
||||
prepareCase("@Value(\"onField\")", "@Value(\"${<*>}\")");
|
||||
@@ -128,6 +168,17 @@ public class ValueCompletionTest {
|
||||
"@Value(\"${spring.prop1<*>}\")");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDollarWithBracketsWithParamCompletion() throws Exception {
|
||||
prepareCase("@Value(\"onField\")", "@Value(value=\"${<*>}\")");
|
||||
prepareDefaultIndexData();
|
||||
|
||||
assertAnnotationCompletions(
|
||||
"@Value(value=\"${data.prop2<*>}\")",
|
||||
"@Value(value=\"${else.prop3<*>}\")",
|
||||
"@Value(value=\"${spring.prop1<*>}\")");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyStringLiteralCompletion() throws Exception {
|
||||
prepareCase("@Value(\"onField\")", "@Value(\"<*>\")");
|
||||
|
||||
Reference in New Issue
Block a user