Bean completion invocation fixes
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016-2017 Pivotal, Inc.
|
||||
* Copyright (c) 2016, 2025 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
|
||||
@@ -15,7 +15,7 @@ import java.util.Comparator;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
|
||||
public abstract class ScoreableProposal implements ICompletionProposal {
|
||||
public abstract class AbstractScoreableProposal implements ICompletionProposalWithScore {
|
||||
|
||||
public static final double DEEMP_EXISTS = 0.1;
|
||||
public static final double DEEMP_DEPRECATION = 0.2;
|
||||
@@ -34,21 +34,21 @@ public abstract class ScoreableProposal implements ICompletionProposal {
|
||||
public static final Comparator<ICompletionProposal> COMPARATOR = new Comparator<ICompletionProposal>() {
|
||||
@Override
|
||||
public int compare(ICompletionProposal p1, ICompletionProposal p2) {
|
||||
if (p1 instanceof ScoreableProposal && p2 instanceof ScoreableProposal) {
|
||||
double s1 = ((ScoreableProposal)p1).getScore();
|
||||
double s2 = ((ScoreableProposal)p2).getScore();
|
||||
if (p1 instanceof ICompletionProposalWithScore && p2 instanceof ICompletionProposalWithScore) {
|
||||
double s1 = ((ICompletionProposalWithScore)p1).getScore();
|
||||
double s2 = ((ICompletionProposalWithScore)p2).getScore();
|
||||
if (s1 == s2) {
|
||||
String name1 = ((ScoreableProposal)p1).getLabel();
|
||||
String name2 = ((ScoreableProposal)p2).getLabel();
|
||||
String name1 = ((ICompletionProposalWithScore)p1).getLabel();
|
||||
String name2 = ((ICompletionProposalWithScore)p2).getLabel();
|
||||
return name1.compareTo(name2);
|
||||
} else {
|
||||
return Double.compare(s2, s1);
|
||||
}
|
||||
}
|
||||
if (p1 instanceof ScoreableProposal) {
|
||||
if (p1 instanceof ICompletionProposalWithScore) {
|
||||
return -1;
|
||||
}
|
||||
if (p2 instanceof ScoreableProposal) {
|
||||
if (p2 instanceof ICompletionProposalWithScore) {
|
||||
return +1;
|
||||
}
|
||||
return p1.getLabel().compareTo(p2.getLabel());
|
||||
@@ -59,7 +59,7 @@ public abstract class ScoreableProposal implements ICompletionProposal {
|
||||
return getBaseScore() - deemphasizedBy;
|
||||
}
|
||||
@Override
|
||||
public ScoreableProposal deemphasize(double howmuch) {
|
||||
public AbstractScoreableProposal deemphasize(double howmuch) {
|
||||
Assert.isLegal(howmuch>=0.0);
|
||||
deemphasizedBy+= howmuch*DEEMP_VALUE;
|
||||
return this;
|
||||
@@ -0,0 +1,17 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2025 Broadcom, 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:
|
||||
* Broadcom, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.languageserver.completion;
|
||||
|
||||
public interface ICompletionProposalWithScore extends ICompletionProposal {
|
||||
|
||||
double getScore();
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017, 2023 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2025 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
|
||||
@@ -23,7 +23,7 @@ import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public abstract class TransformedCompletion extends ScoreableProposal {
|
||||
public abstract class TransformedCompletion extends AbstractScoreableProposal {
|
||||
|
||||
protected final ICompletionProposal original;
|
||||
|
||||
@@ -71,8 +71,8 @@ public abstract class TransformedCompletion extends ScoreableProposal {
|
||||
|
||||
@Override
|
||||
public double getBaseScore() {
|
||||
if (original instanceof ScoreableProposal) {
|
||||
return ((ScoreableProposal) original).getScore();
|
||||
if (original instanceof AbstractScoreableProposal) {
|
||||
return ((AbstractScoreableProposal) original).getScore();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2023 VMware Inc.
|
||||
* Copyright (c) 2016, 2025 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
|
||||
@@ -218,7 +218,7 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
|
||||
cancelToken.checkCanceled();
|
||||
|
||||
List<ICompletionProposal> completions = filter(rawCompletionList.completionItems());
|
||||
Collections.sort(completions, ScoreableProposal.COMPARATOR);
|
||||
Collections.sort(completions, AbstractScoreableProposal.COMPARATOR);
|
||||
|
||||
cancelToken.checkCanceled();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016-2017 Pivotal, Inc.
|
||||
* Copyright (c) 2016, 2025 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
|
||||
@@ -14,7 +14,7 @@ package org.springframework.ide.vscode.commons.yaml.completion;
|
||||
import org.eclipse.lsp4j.CompletionItemKind;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.util.Renderables;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
@@ -27,7 +27,7 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
|
||||
private static final int ERROR_COMPLETION_SCORE = -10000000;
|
||||
|
||||
public static class BeanPropertyProposal extends ScoreableProposal {
|
||||
public static class BeanPropertyProposal extends AbstractScoreableProposal {
|
||||
|
||||
// private IDocument doc;
|
||||
private String contextProperty;
|
||||
@@ -81,7 +81,7 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
}
|
||||
}
|
||||
|
||||
public class ValueProposal extends ScoreableProposal {
|
||||
public class ValueProposal extends AbstractScoreableProposal {
|
||||
|
||||
private String value;
|
||||
private String label;
|
||||
@@ -137,7 +137,7 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ErrorProposal extends ScoreableProposal {
|
||||
public static final class ErrorProposal extends AbstractScoreableProposal {
|
||||
private final String longMessage;
|
||||
private String shortMessage;
|
||||
private String filterText;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2019 Pivotal, Inc.
|
||||
* Copyright (c) 2016, 2025 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
|
||||
@@ -10,8 +10,8 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.yaml.completion;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.DEEMP_DASH_PROPOSAL;
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.DEEMP_DEPRECATION;
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal.DEEMP_DASH_PROPOSAL;
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal.DEEMP_DEPRECATION;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -25,7 +25,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.TransformedCompletion;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.PlaceHolderString;
|
||||
import org.springframework.ide.vscode.commons.util.CollectionUtil;
|
||||
@@ -206,7 +206,7 @@ public class YTypeAssistContext extends AbstractYamlAssistContext {
|
||||
ICompletionProposal completion = completionFactory().beanProperty(doc.getDocument(),
|
||||
contextPath.toPropString(), getType(),
|
||||
query, p, score, edits, typeUtil);
|
||||
if (p.isDeprecated() && completion instanceof ScoreableProposal) {
|
||||
if (p.isDeprecated() && completion instanceof AbstractScoreableProposal) {
|
||||
completion.deemphasize(DEEMP_DEPRECATION);
|
||||
}
|
||||
proposals.add(completion);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2024 Pivotal, Inc.
|
||||
* Copyright (c) 2016, 2025 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
|
||||
@@ -10,8 +10,8 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.yaml.completion;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.DEEMP_DEDENTED_PROPOSAL;
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.DEEMP_INDENTED_PROPOSAL;
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal.DEEMP_DEDENTED_PROPOSAL;
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal.DEEMP_INDENTED_PROPOSAL;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -26,7 +26,7 @@ import org.springframework.ide.vscode.commons.languageserver.completion.Document
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.InternalCompletionList;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.TransformedCompletion;
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import org.springframework.ide.vscode.commons.util.Unicodes;
|
||||
@@ -97,7 +97,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
double deempasizeBy = 0.0;
|
||||
for (SNode contextNode : contextNodes) {
|
||||
completions.addAll(getRelaxedCompletions(offset, doc, current, contextNode, baseIndent, deempasizeBy));
|
||||
deempasizeBy += ScoreableProposal.DEEMP_NEXT_CONTEXT;
|
||||
deempasizeBy += AbstractScoreableProposal.DEEMP_NEXT_CONTEXT;
|
||||
}
|
||||
return new InternalCompletionList(completions, false);
|
||||
} else {
|
||||
@@ -129,7 +129,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
List<ICompletionProposal> transformed = new ArrayList<>();
|
||||
for (ICompletionProposal p : completions) {
|
||||
int targetIndent = p.getLabel().startsWith("- ") ? dashyIndent : plainIndent;
|
||||
ScoreableProposal p_fixed = indentFix((ScoreableProposal)p, targetIndent - baseIndent, currentNode, contextNode, doc);
|
||||
AbstractScoreableProposal p_fixed = indentFix((AbstractScoreableProposal)p, targetIndent - baseIndent, currentNode, contextNode, doc);
|
||||
if (p_fixed!=null) {
|
||||
p_fixed.deemphasize(deempasizeBy);
|
||||
transformed.add(p_fixed);
|
||||
@@ -140,7 +140,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected ScoreableProposal indentFix(ScoreableProposal p, int fixIndentBy, SNode currentNode, SNode contextNode, YamlDocument doc) {
|
||||
protected AbstractScoreableProposal indentFix(AbstractScoreableProposal p, int fixIndentBy, SNode currentNode, SNode contextNode, YamlDocument doc) {
|
||||
if (fixIndentBy==0) {
|
||||
return p;
|
||||
} else if (fixIndentBy>0) {
|
||||
@@ -190,7 +190,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
: contextNode.getIndent() + YamlIndentUtil.INDENT_BY;
|
||||
}
|
||||
|
||||
public ScoreableProposal dedented(ICompletionProposal proposal, int numSpacesToRemove, IDocument doc) {
|
||||
public AbstractScoreableProposal dedented(ICompletionProposal proposal, int numSpacesToRemove, IDocument doc) {
|
||||
Assert.isLegal(numSpacesToRemove>0);
|
||||
int spacesEnd = proposal.getTextEdit().getFirstEditStart();
|
||||
int spacesStart = spacesEnd-numSpacesToRemove;
|
||||
@@ -198,7 +198,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
String spaces = new DocumentRegion(doc, spacesStart, spacesEnd).toString();
|
||||
YamlIndentUtil indenter = new YamlIndentUtil(doc);
|
||||
if (spaces.length()==numSpacesToRemove && SPACES.matcher(spaces).matches()) {
|
||||
ScoreableProposal transformed = new TransformedCompletion(proposal) {
|
||||
AbstractScoreableProposal transformed = new TransformedCompletion(proposal) {
|
||||
@Override public String tranformLabel(String originalLabel) {
|
||||
return Strings.repeat(Unicodes.LEFT_ARROW+" ", numArrows) + originalLabel;
|
||||
}
|
||||
@@ -228,9 +228,9 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ScoreableProposal indented(ICompletionProposal proposal, String indentStr, YamlDocument doc) {
|
||||
public AbstractScoreableProposal indented(ICompletionProposal proposal, String indentStr, YamlDocument doc) {
|
||||
int numArrows = (indentStr.length()+1)/2;
|
||||
ScoreableProposal transformed = new TransformedCompletion(proposal) {
|
||||
AbstractScoreableProposal transformed = new TransformedCompletion(proposal) {
|
||||
@Override public String tranformLabel(String originalLabel) {
|
||||
return Strings.repeat(Unicodes.RIGHT_ARROW+" ", numArrows) + originalLabel;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2023 Pivotal, Inc.
|
||||
* Copyright (c) 2015, 2025 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
|
||||
@@ -12,11 +12,11 @@ package org.springframework.ide.vscode.boot.common;
|
||||
|
||||
import org.eclipse.lsp4j.CompletionItemKind;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YType;
|
||||
|
||||
public abstract class AbstractPropertyProposal extends ScoreableProposal {
|
||||
public abstract class AbstractPropertyProposal extends AbstractScoreableProposal {
|
||||
|
||||
@Override
|
||||
public String getDetail() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2014, 2023 Pivotal, Inc.
|
||||
* Copyright (c) 2014, 2025 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
|
||||
@@ -18,7 +18,7 @@ import org.springframework.ide.vscode.boot.metadata.types.TypeUtil;
|
||||
import org.springframework.ide.vscode.boot.metadata.types.TypedProperty;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.util.FuzzyMap.Match;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
@@ -28,7 +28,7 @@ import org.springframework.ide.vscode.commons.yaml.schema.YType;
|
||||
public class PropertyCompletionFactory {
|
||||
|
||||
public ICompletionProposal valueProposal(String value, String query, String niceTypeName, double score, DocumentEdits edits, Renderable info) {
|
||||
return new ScoreableProposal() {
|
||||
return new AbstractScoreableProposal() {
|
||||
|
||||
@Override
|
||||
public DocumentEdits getTextEdit() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2024 Broadcom
|
||||
* Copyright (c) 2024, 2025 Broadcom
|
||||
* 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
|
||||
@@ -12,13 +12,13 @@ package org.springframework.ide.vscode.boot.java.annotations;
|
||||
|
||||
import org.eclipse.lsp4j.CompletionItemKind;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class AnnotationAttributeCompletionProposal extends ScoreableProposal {
|
||||
public class AnnotationAttributeCompletionProposal extends AbstractScoreableProposal {
|
||||
|
||||
private final AnnotationAttributeProposal coreProposal;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017, 2024 Broadcom, Inc.
|
||||
* Copyright (c) 2017, 2025 Broadcom, 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
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.CompletionItemKind;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposalWithScore;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.InjectBeanCompletionRecipe;
|
||||
@@ -30,7 +30,7 @@ import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
* @author Udayani V
|
||||
* @author Alex Boyko
|
||||
*/
|
||||
public class BeanCompletionProposal implements ICompletionProposal {
|
||||
public class BeanCompletionProposal implements ICompletionProposalWithScore {
|
||||
|
||||
private DocumentEdits edits;
|
||||
private IDocument doc;
|
||||
@@ -38,14 +38,17 @@ public class BeanCompletionProposal implements ICompletionProposal {
|
||||
private String beanType;
|
||||
private String className;
|
||||
private RewriteRefactorings rewriteRefactorings;
|
||||
private double score;
|
||||
|
||||
public BeanCompletionProposal(DocumentEdits edits, IDocument doc, String beanId, String beanType, String className,
|
||||
double score,
|
||||
RewriteRefactorings rewriteRefactorings) {
|
||||
this.edits = edits;
|
||||
this.doc = doc;
|
||||
this.beanId = beanId;
|
||||
this.beanType = beanType;
|
||||
this.className = className;
|
||||
this.score = score;
|
||||
this.rewriteRefactorings = rewriteRefactorings;
|
||||
}
|
||||
|
||||
@@ -82,6 +85,10 @@ public class BeanCompletionProposal implements ICompletionProposal {
|
||||
.withRecipeScope(RecipeScope.NODE);
|
||||
return Optional.of(rewriteRefactorings.createFixCommand("Inject bean '%s'".formatted(beanId), f));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,13 +10,19 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.beans;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.Block;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.IAnnotationBinding;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.SimpleName;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.jdt.core.dom.VariableDeclaration;
|
||||
@@ -30,6 +36,7 @@ import org.springframework.ide.vscode.commons.languageserver.completion.Document
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
|
||||
import org.springframework.ide.vscode.commons.util.FuzzyMatcher;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
/**
|
||||
@@ -53,7 +60,7 @@ public class BeanCompletionProvider implements CompletionProvider {
|
||||
@Override
|
||||
public void provideCompletions(ASTNode node, int offset, TextDocument doc,
|
||||
Collection<ICompletionProposal> completions) {
|
||||
if (node instanceof SimpleName) {
|
||||
if (node instanceof SimpleName || node instanceof Block) {
|
||||
try {
|
||||
// Don't look at anything inside Annotation or VariableDelcaration node
|
||||
for (ASTNode n = node; n != null; n = n.getParent()) {
|
||||
@@ -77,14 +84,36 @@ public class BeanCompletionProvider implements CompletionProvider {
|
||||
if (isSpringComponent(topLevelClass)) {
|
||||
String className = getFullyQualifiedName(topLevelClass);
|
||||
Bean[] beans = this.springIndex.getBeansOfProject(project.getElementName());
|
||||
ITypeBinding topLevelBeanType = topLevelClass.resolveBinding();
|
||||
Set<String> declaredFiledsTypes = Arrays.stream(topLevelBeanType.getDeclaredFields())
|
||||
.map(vd -> vd.getType())
|
||||
.filter(Objects::nonNull)
|
||||
.map(t -> t.getQualifiedName())
|
||||
.collect(Collectors.toSet());
|
||||
final String prefix = node instanceof Block ? "" : node.toString();
|
||||
for (Bean bean : beans) {
|
||||
DocumentEdits edits = new DocumentEdits(doc, false);
|
||||
edits.replace(offset - node.toString().length(), offset, bean.getName());
|
||||
// If current class is a bean - ignore it
|
||||
if (className.equals(bean.getType())) {
|
||||
continue;
|
||||
}
|
||||
// Filter out beans already injected into this class
|
||||
if (declaredFiledsTypes.contains(bean.getType())) {
|
||||
continue;
|
||||
}
|
||||
double score = FuzzyMatcher.matchScore(prefix, bean.getName());
|
||||
if (score > 0) {
|
||||
DocumentEdits edits = new DocumentEdits(doc, false);
|
||||
if (node instanceof Block) {
|
||||
edits.insert(offset, bean.getName());
|
||||
} else {
|
||||
edits.replace(offset - prefix.length(), offset, bean.getName());
|
||||
}
|
||||
|
||||
BeanCompletionProposal proposal = new BeanCompletionProposal(edits, doc, bean.getName(),
|
||||
bean.getType(), className, rewriteRefactorings);
|
||||
BeanCompletionProposal proposal = new BeanCompletionProposal(edits, doc, bean.getName(),
|
||||
bean.getType(), className, score, rewriteRefactorings);
|
||||
|
||||
completions.add(proposal);
|
||||
completions.add(proposal);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -127,9 +156,10 @@ public class BeanCompletionProvider implements CompletionProvider {
|
||||
}
|
||||
|
||||
private static String getFullyQualifiedName(TypeDeclaration typeDecl) {
|
||||
if (typeDecl.resolveBinding() != null) {
|
||||
String qualifiedName = typeDecl.resolveBinding().getQualifiedName();
|
||||
return qualifiedName.replaceAll("\\.(?=[^\\.]+$)", "\\$");
|
||||
ITypeBinding binding = typeDecl.resolveBinding();
|
||||
if (binding != null) {
|
||||
String qualifiedName = binding.getQualifiedName();
|
||||
return qualifiedName/*.replaceAll("\\.(?=[^\\.]+$)", "\\$")*/;
|
||||
}
|
||||
CompilationUnit cu = (CompilationUnit) typeDecl.getRoot();
|
||||
String packageName = cu.getPackage() != null ? cu.getPackage().getName().getFullyQualifiedName() : "";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017, 2020 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2025 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
|
||||
@@ -14,14 +14,14 @@ import org.eclipse.lsp4j.CompletionItemKind;
|
||||
import org.springframework.ide.vscode.boot.common.InformationTemplates;
|
||||
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.util.FuzzyMap.Match;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class ValuePropertyKeyProposal extends ScoreableProposal {
|
||||
public class ValuePropertyKeyProposal extends AbstractScoreableProposal {
|
||||
|
||||
private static final String EMPTY_DETAIL = "";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2019, 2024 Pivotal, Inc.
|
||||
* Copyright (c) 2019, 2025 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
|
||||
@@ -15,13 +15,13 @@ import java.util.function.Supplier;
|
||||
|
||||
import org.eclipse.lsp4j.CompletionItemKind;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class GenericXMLCompletionProposal extends ScoreableProposal {
|
||||
public class GenericXMLCompletionProposal extends AbstractScoreableProposal {
|
||||
|
||||
private final String label;
|
||||
private final CompletionItemKind kind;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2023 Pivotal, Inc.
|
||||
* Copyright (c) 2015, 2025 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
|
||||
@@ -10,7 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.yaml.completions;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.DEEMP_EXISTS;
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal.DEEMP_EXISTS;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -53,7 +53,7 @@ import org.springframework.ide.vscode.commons.java.IType;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.LazyProposalApplier;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.AbstractScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.util.CollectionUtil;
|
||||
import org.springframework.ide.vscode.commons.util.FuzzyMap.Match;
|
||||
import org.springframework.ide.vscode.commons.util.FuzzyMatcher;
|
||||
@@ -466,7 +466,7 @@ public abstract class ApplicationYamlAssistContext extends AbstractYamlAssistCon
|
||||
matchingProps.stream().forEach(match -> {
|
||||
try {
|
||||
DocumentEdits edits = createEdits(doc, node, offset, query, match);
|
||||
ScoreableProposal completion = completionFactory.property(
|
||||
AbstractScoreableProposal completion = completionFactory.property(
|
||||
doc.getDocument(), edits, match, typeUtil
|
||||
);
|
||||
String prefix = indexNav.getPrefix();
|
||||
|
||||
@@ -65,6 +65,7 @@ public class BeanCompletionProviderTest {
|
||||
private Bean bean3;
|
||||
private Bean bean4;
|
||||
private Bean bean5;
|
||||
private Bean bean6;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws Exception {
|
||||
@@ -86,8 +87,9 @@ public class BeanCompletionProviderTest {
|
||||
bean3 = new Bean("visitRepository", "org.springframework.samples.petclinic.owner.VisitRepository", new Location(tempJavaDocUri, new Range(new Position(1,1), new Position(1, 20))), null, null, null, false, "symbolLabel");
|
||||
bean4 = new Bean("visitService", "org.springframework.samples.petclinic.owner.VisitService", new Location(tempJavaDocUri, new Range(new Position(1,1), new Position(1, 20))), null, null, null, false, "symbolLabel");
|
||||
bean5 = new Bean("petService", "org.springframework.samples.petclinic.pet.Inner.PetService", new Location(tempJavaDocUri, new Range(new Position(1,1), new Position(1, 20))), null, null, null, false, "symbolLabel");
|
||||
bean6 = new Bean("testBeanCompletionClass", "org.sample.test.TestBeanCompletionClass", new Location(tempJavaDocUri, new Range(new Position(1,1), new Position(1, 20))), null, null, null, false, "symbolLabel");
|
||||
|
||||
springIndex.updateBeans(project.getElementName(), new Bean[] {bean1, bean2, bean3, bean4, bean5});
|
||||
springIndex.updateBeans(project.getElementName(), new Bean[] {bean1, bean2, bean3, bean4, bean5, bean6});
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -97,7 +99,7 @@ public class BeanCompletionProviderTest {
|
||||
|
||||
@Test
|
||||
public void testBeanCompletion_firstCompletion() throws Exception {
|
||||
assertCompletions(getCompletion("owner<*>"), new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 0,
|
||||
assertCompletions(getCompletion("owner<*>"), new String[] {"ownerRepository", "ownerService"}, 0,
|
||||
"""
|
||||
package org.sample.test;
|
||||
|
||||
@@ -122,7 +124,32 @@ ownerRepository<*>
|
||||
|
||||
@Test
|
||||
public void testBeanCompletion_secondCompletion() throws Exception {
|
||||
assertCompletions(getCompletion("owner<*>"), new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 1,
|
||||
assertCompletions(getCompletion("owner<*>"), new String[] {"ownerRepository", "ownerService"}, 1,
|
||||
"""
|
||||
package org.sample.test;
|
||||
|
||||
import org.springframework.samples.petclinic.owner.OwnerService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
@Controller
|
||||
public class TestBeanCompletionClass {
|
||||
|
||||
private final OwnerService ownerService;
|
||||
|
||||
TestBeanCompletionClass(OwnerService ownerService) {
|
||||
this.ownerService = ownerService;
|
||||
}
|
||||
|
||||
public void test() {
|
||||
ownerService<*>
|
||||
}
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noPrefix_secondCompletion() throws Exception {
|
||||
assertCompletions(getCompletion("<*>"), new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 1,
|
||||
"""
|
||||
package org.sample.test;
|
||||
|
||||
@@ -147,7 +174,7 @@ ownerService<*>
|
||||
|
||||
@Test
|
||||
public void testBeanCompletion_injectInnerClass() throws Exception {
|
||||
assertCompletions(getCompletion("owner<*>"), new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 2,
|
||||
assertCompletions(getCompletion("<*>"), new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 2,
|
||||
"""
|
||||
package org.sample.test;
|
||||
|
||||
@@ -199,7 +226,72 @@ petService<*>
|
||||
}
|
||||
""";
|
||||
|
||||
assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 1,
|
||||
assertCompletions(content, new String[] {"ownerRepository", "ownerService"}, 1,
|
||||
"""
|
||||
package org.sample.test;
|
||||
|
||||
import org.springframework.samples.petclinic.owner.OwnerRepository;
|
||||
import org.springframework.samples.petclinic.owner.OwnerService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
@Controller
|
||||
public class TestBeanCompletionClass {
|
||||
private final OwnerRepository ownerRepository;
|
||||
|
||||
TestBeanCompletionClass(OwnerRepository ownerRepository) {
|
||||
this.ownerRepository = ownerRepository;
|
||||
}
|
||||
|
||||
public void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
public class TestBeanCompletionSecondClass {
|
||||
|
||||
private final OwnerService ownerService;
|
||||
|
||||
TestBeanCompletionSecondClass(OwnerService ownerService) {
|
||||
this.ownerService = ownerService;
|
||||
}
|
||||
|
||||
public void test() {
|
||||
ownerService<*>
|
||||
}
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noPrefix_multipleClasses() throws Exception {
|
||||
String content = """
|
||||
package org.sample.test;
|
||||
|
||||
import org.springframework.samples.petclinic.owner.OwnerRepository;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
@Controller
|
||||
public class TestBeanCompletionClass {
|
||||
private final OwnerRepository ownerRepository;
|
||||
|
||||
TestBeanCompletionClass(OwnerRepository ownerRepository) {
|
||||
this.ownerRepository = ownerRepository;
|
||||
}
|
||||
|
||||
public void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
public class TestBeanCompletionSecondClass {
|
||||
|
||||
public void test() {
|
||||
<*>
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "testBeanCompletionClass", "visitRepository", "visitService"}, 1,
|
||||
"""
|
||||
package org.sample.test;
|
||||
|
||||
@@ -279,13 +371,13 @@ public class TestBeanCompletionClass {
|
||||
public class Inner {
|
||||
|
||||
public void test() {
|
||||
ownerRe<*>
|
||||
owner<*>
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 0,
|
||||
assertCompletions(content, new String[] {"ownerRepository", "ownerService"}, 0,
|
||||
"""
|
||||
package org.sample.test;
|
||||
|
||||
@@ -330,6 +422,68 @@ public class TestBeanCompletionClass {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beansPresent() throws Exception {
|
||||
String content = """
|
||||
package org.sample.test;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
@Controller
|
||||
public class TestBeanCompletionSecondClass {
|
||||
private final TestBeanCompletionClass testBeanCompletionClass;
|
||||
|
||||
TestBeanCompletionSecondClass(TestBeanCompletionClass testBeanCompletionClass) {
|
||||
this.testBeanCompletionClass = testBeanCompletionClass;
|
||||
}
|
||||
|
||||
public void test() {
|
||||
owner<*>
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
public class TestBeanCompletionClass {
|
||||
|
||||
public void test() {
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
assertCompletions(content, new String[] {"ownerRepository", "ownerService"}, 0,
|
||||
"""
|
||||
package org.sample.test;
|
||||
|
||||
import org.springframework.samples.petclinic.owner.OwnerRepository;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
@Controller
|
||||
public class TestBeanCompletionSecondClass {
|
||||
|
||||
private final OwnerRepository ownerRepository;
|
||||
private final TestBeanCompletionClass testBeanCompletionClass;
|
||||
|
||||
TestBeanCompletionSecondClass(TestBeanCompletionClass testBeanCompletionClass, OwnerRepository ownerRepository) {
|
||||
this.testBeanCompletionClass = testBeanCompletionClass;
|
||||
this.ownerRepository = ownerRepository;
|
||||
}
|
||||
|
||||
public void test() {
|
||||
ownerRepository<*>
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
public class TestBeanCompletionClass {
|
||||
|
||||
public void test() {
|
||||
}
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void assertCompletions(String completionLine, String[] expectedCompletions, int chosenCompletion, String expectedResult) throws Exception {
|
||||
assertCompletions(completionLine, expectedCompletions.length, expectedCompletions, chosenCompletion, expectedResult);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user