Skip to content

Commit 006c814

Browse files
support blueprint's factory-method and factory-ref (#1154)
* support blueprint's factory-method and factory-ref references and code completion * fix bean method references, fixes #1155 * try fixing gradle validation failures by using different action, see gradle/wrapper-validation-action#40, fixes #1157 --------- Co-authored-by: Claus Ibsen <claus.ibsen@gmail.com>
1 parent 12b2441 commit 006c814

36 files changed

Lines changed: 1325 additions & 79 deletions

src/main/java/com/github/cameltooling/idea/completion/contributor/CamelContributor.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.intellij.codeInsight.completion.CompletionParameters;
2727
import com.intellij.codeInsight.completion.CompletionProvider;
2828
import com.intellij.codeInsight.completion.CompletionResultSet;
29+
import com.intellij.codeInsight.completion.CompletionType;
2930
import com.intellij.codeInsight.completion.CompletionUtil;
3031
import com.intellij.patterns.InitialPatternCondition;
3132
import com.intellij.patterns.PsiFilePattern;
@@ -63,10 +64,19 @@ public void addCompletions(@NotNull CompletionParameters parameters,
6364
if (parameters.getOriginalFile().getProject().getService(CamelService.class).isCamelProject()) {
6465
CompletionQuery query = parsePsiElement(parameters);
6566
camelCompletionExtensions.stream()
67+
.filter(p -> isSupportedCompletionType(p, parameters.getCompletionType()))
6668
.filter(p -> p.isValid(parameters, context, query))
6769
.forEach(p -> p.addCompletions(parameters, context, resultSet, query));
6870
}
6971
}
72+
73+
private boolean isSupportedCompletionType(CamelCompletionExtension p, CompletionType completionType) {
74+
return switch (completionType) {
75+
case BASIC -> true;
76+
case SMART -> p.supportsSmartCompletion();
77+
default -> false;
78+
};
79+
}
7080
}
7181

7282
/**

src/main/java/com/github/cameltooling/idea/completion/contributor/CamelXmlReferenceContributor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.github.cameltooling.idea.completion.contributor;
1818

1919
import com.github.cameltooling.idea.completion.extension.BeanReferenceCompletionExtension;
20+
import com.github.cameltooling.idea.completion.extension.BlueprintFactoryMethodCompletionExtension;
2021
import com.github.cameltooling.idea.completion.extension.BlueprintPropertyNameCompletionExtension;
2122
import com.github.cameltooling.idea.completion.extension.CamelEndpointNameCompletionExtension;
2223
import com.github.cameltooling.idea.completion.extension.CamelEndpointSmartCompletionExtension;
@@ -42,10 +43,11 @@ public class CamelXmlReferenceContributor extends CamelContributor {
4243
public CamelXmlReferenceContributor() {
4344
addCompletionExtension(new BeanReferenceCompletionExtension());
4445
addCompletionExtension(new BlueprintPropertyNameCompletionExtension());
46+
addCompletionExtension(new BlueprintFactoryMethodCompletionExtension());
4547
addCompletionExtension(new CamelEndpointNameCompletionExtension());
4648
addCompletionExtension(new CamelEndpointSmartCompletionExtension(true));
4749
addCompletionExtension(new CamelPropertyPlaceholderSmartCompletionExtension());
48-
extend(CompletionType.BASIC,
50+
extend(null, // any completion type
4951
psiElement().and(psiElement().inside(PsiFile.class).inFile(matchFileType("xml"))),
5052
new CompositeCompletionProvider(getCamelCompletionExtensions())
5153
);

src/main/java/com/github/cameltooling/idea/completion/extension/BeanReferenceCompletionExtension.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424
import com.github.cameltooling.idea.reference.blueprint.model.ReferenceableBeanId;
2525
import com.github.cameltooling.idea.service.CamelPreferenceService;
2626
import com.github.cameltooling.idea.util.BeanUtils;
27+
import com.intellij.codeInsight.completion.CompletionParameters;
2728
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
2829
import com.intellij.codeInsight.lookup.LookupElement;
2930
import com.intellij.openapi.module.Module;
3031
import com.intellij.openapi.module.ModuleUtilCore;
32+
import com.intellij.psi.PsiClass;
3133
import com.intellij.psi.PsiElement;
3234
import com.intellij.psi.PsiType;
3335
import org.jetbrains.annotations.NotNull;
@@ -42,15 +44,20 @@ public BeanReferenceCompletionExtension() {
4244
}
4345

4446
@Override
45-
protected List<LookupElement> findResults(@NotNull PsiElement element, @NotNull String query) {
47+
protected List<LookupElement> findResults(@NotNull CompletionParameters parameters, @NotNull PsiElement element, @NotNull String query) {
4648
List<ReferenceableBeanId> targets = findTargets(element, query);
4749
return targets.stream()
4850
.map(bean -> createLookupElementBuilder(bean.getId(), bean.getElement())
49-
.withTypeText(bean.getReferencedClass() == null ? null : bean.getReferencedClass().getClassSimpleName())
51+
.withTypeText(getReferencedClassName(bean))
5052
.withAutoCompletionPolicy(AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE))
5153
.collect(Collectors.toList());
5254
}
5355

56+
private String getReferencedClassName(ReferenceableBeanId bean) {
57+
PsiClass psiClass = BeanUtils.getService().getReferencedClass(bean);
58+
return psiClass != null ? psiClass.getName() : null;
59+
}
60+
5461
private List<ReferenceableBeanId> findTargets(PsiElement element, String query) {
5562
Module module = ModuleUtilCore.findModuleForPsiElement(element);
5663
if (module == null) {
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.github.cameltooling.idea.completion.extension;
18+
19+
import com.github.cameltooling.idea.completion.lookup.MethoLookupElementFactory;
20+
import com.github.cameltooling.idea.reference.blueprint.model.FactoryBeanMethodReference;
21+
import com.github.cameltooling.idea.util.BeanUtils;
22+
import com.intellij.codeInsight.completion.CompletionParameters;
23+
import com.intellij.codeInsight.completion.CompletionType;
24+
import com.intellij.codeInsight.lookup.LookupElement;
25+
import com.intellij.psi.PsiElement;
26+
import com.intellij.psi.PsiMethod;
27+
import com.intellij.psi.PsiType;
28+
import com.intellij.psi.util.PsiTreeUtil;
29+
import com.intellij.psi.xml.XmlAttribute;
30+
import com.intellij.psi.xml.XmlTag;
31+
import org.jetbrains.annotations.NotNull;
32+
33+
import java.util.HashSet;
34+
import java.util.List;
35+
import java.util.Set;
36+
37+
public class BlueprintFactoryMethodCompletionExtension extends ReferenceBasedCompletionExtension<FactoryBeanMethodReference> {
38+
39+
public BlueprintFactoryMethodCompletionExtension() {
40+
super(FactoryBeanMethodReference.class);
41+
}
42+
43+
@Override
44+
public boolean supportsSmartCompletion() {
45+
return true;
46+
}
47+
48+
@Override
49+
protected List<LookupElement> findResults(@NotNull CompletionParameters parameters, @NotNull PsiElement element, @NotNull String query) {
50+
XmlAttribute xAttr = PsiTreeUtil.getParentOfType(element, XmlAttribute.class, false);
51+
if (xAttr != null && xAttr.getLocalName().equals("factory-method")) {
52+
XmlTag tag = xAttr.getParent();
53+
BeanUtils beanUtils = BeanUtils.getService();
54+
if (beanUtils.isBeanDeclaration(tag)) {
55+
try {
56+
List<PsiMethod> methods = beanUtils.findFactoryMethods(tag, null);
57+
if (parameters.getCompletionType().equals(CompletionType.SMART)) {
58+
methods = beanUtils.filterPossibleBeanFactoryMethods(tag, methods);
59+
}
60+
return convertMethodsToLookupElements(methods);
61+
} catch (BeanUtils.FactoryBeanMethodCycleException e) {
62+
return List.of();
63+
}
64+
}
65+
}
66+
return List.of();
67+
}
68+
69+
private List<LookupElement> convertMethodsToLookupElements(List<PsiMethod> methods) {
70+
Set<String> names = new HashSet<>();
71+
return methods.stream()
72+
.filter(m -> {
73+
if (names.contains(m.getName())) {
74+
return false;
75+
}
76+
names.add(m.getName());
77+
return true;
78+
})
79+
.map(method -> {
80+
PsiType rt = method.getReturnType();
81+
return MethoLookupElementFactory.create(method, method.getName(), rt == null ? null : rt.getPresentableText());
82+
})
83+
.toList();
84+
}
85+
86+
}

src/main/java/com/github/cameltooling/idea/completion/extension/BlueprintPropertyNameCompletionExtension.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.stream.Collectors;
2222
import com.github.cameltooling.idea.reference.blueprint.PropertyNameReference;
2323
import com.github.cameltooling.idea.util.BeanUtils;
24+
import com.intellij.codeInsight.completion.CompletionParameters;
2425
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
2526
import com.intellij.codeInsight.lookup.LookupElement;
2627
import com.intellij.psi.PsiClass;
@@ -42,7 +43,8 @@ public BlueprintPropertyNameCompletionExtension() {
4243
}
4344

4445
@Override
45-
protected List<LookupElement> findResults(@NotNull PsiElement element,
46+
protected List<LookupElement> findResults(@NotNull CompletionParameters parameters,
47+
@NotNull PsiElement element,
4648
@NotNull String query) {
4749
XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
4850
if (tag != null) {

src/main/java/com/github/cameltooling/idea/completion/extension/CamelCompletionExtension.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,8 @@ public interface CamelCompletionExtension {
4242
*/
4343
boolean isValid(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, CompletionQuery query);
4444

45+
default boolean supportsSmartCompletion() {
46+
return false;
47+
}
48+
4549
}

src/main/java/com/github/cameltooling/idea/completion/extension/CamelEndpointNameCompletionExtension.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
public class CamelEndpointNameCompletionExtension extends SimpleCompletionExtension {
3939

4040
@Override
41-
protected List<LookupElement> findResults(@NotNull PsiElement element, @NotNull String query) {
41+
protected List<LookupElement> findResults(@NotNull CompletionParameters parameters, @NotNull PsiElement element, @NotNull String query) {
4242
Module module = ModuleUtilCore.findModuleForPsiElement(element);
4343
List<PsiElement> endpointDeclarations = CamelIdeaUtils.getService().findEndpointDeclarations(module, e -> true);
4444
return endpointDeclarations.stream()

src/main/java/com/github/cameltooling/idea/completion/extension/CamelJavaBeanReferenceSmartCompletion.java

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,14 @@
1616
*/
1717
package com.github.cameltooling.idea.completion.extension;
1818

19+
import com.github.cameltooling.idea.completion.lookup.MethoLookupElementFactory;
1920
import com.github.cameltooling.idea.util.CamelIdeaUtils;
2021
import com.github.cameltooling.idea.util.JavaMethodUtils;
2122
import com.intellij.codeInsight.completion.CompletionParameters;
2223
import com.intellij.codeInsight.completion.CompletionProvider;
2324
import com.intellij.codeInsight.completion.CompletionResultSet;
2425
import com.intellij.codeInsight.completion.CompletionUtil;
25-
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
2626
import com.intellij.codeInsight.lookup.LookupElement;
27-
import com.intellij.codeInsight.lookup.LookupElementBuilder;
28-
import com.intellij.icons.AllIcons;
2927
import com.intellij.psi.PsiClass;
3028
import com.intellij.psi.PsiElement;
3129
import com.intellij.psi.PsiMethod;
@@ -58,7 +56,7 @@ protected void addCompletions(@NotNull CompletionParameters completionParameters
5856

5957
List<LookupElement> answer = javaMethodUtils.getBeanAccessibleMethods(methods)
6058
.stream()
61-
.map(method -> buildLookupElement(method, javaMethodUtils.getPresentableMethodWithParameters(method)))
59+
.map(method -> MethoLookupElementFactory.create(method, javaMethodUtils.getPresentableMethodWithParameters(method)))
6260
.collect(toList());
6361

6462
// are there any results then add them
@@ -71,21 +69,4 @@ protected void addCompletions(@NotNull CompletionParameters completionParameters
7169
}
7270
}
7371

74-
@NotNull
75-
private LookupElement buildLookupElement(PsiMethod method, String presentableMethod) {
76-
LookupElementBuilder builder = LookupElementBuilder.create(method);
77-
builder = builder.withPresentableText(presentableMethod);
78-
builder = builder.withTypeText(method.getContainingClass().getName(), true);
79-
builder = builder.withIcon(AllIcons.Nodes.Method);
80-
if (CamelIdeaUtils.getService().isAnnotatedWithHandler(method)) {
81-
//@Handle methods are marked with
82-
builder = builder.withBoldness(true);
83-
}
84-
if (method.isDeprecated()) {
85-
// mark as deprecated
86-
builder = builder.withStrikeoutness(true);
87-
}
88-
return builder.withAutoCompletionPolicy(AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE);
89-
}
90-
9172
}

src/main/java/com/github/cameltooling/idea/completion/extension/SimpleCompletionExtension.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public void addCompletions(@NotNull CompletionParameters parameters, @NotNull Pr
4848
return;
4949
}
5050

51-
List<LookupElement> results = findResults(element, query.valueAtPosition());
51+
List<LookupElement> results = findResults(parameters, element, query.valueAtPosition());
5252
if (!results.isEmpty()) {
5353
resultSet
5454
.withRelevanceSorter(CompletionSorter.emptySorter())
@@ -62,7 +62,8 @@ public boolean isValid(@NotNull CompletionParameters parameters, @NotNull Proces
6262
return isValid(parameters, context, query.valueAtPosition());
6363
}
6464

65-
protected abstract List<LookupElement> findResults(@NotNull PsiElement element, @NotNull String query);
65+
protected abstract List<LookupElement> findResults(@NotNull CompletionParameters parameters, @NotNull PsiElement element, @NotNull String query);
66+
6667
protected abstract boolean isValid(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull String query);
6768

6869

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.github.cameltooling.idea.completion.lookup;
18+
19+
import com.github.cameltooling.idea.util.CamelIdeaUtils;
20+
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
21+
import com.intellij.codeInsight.lookup.LookupElement;
22+
import com.intellij.codeInsight.lookup.LookupElementBuilder;
23+
import com.intellij.icons.AllIcons;
24+
import com.intellij.psi.PsiClass;
25+
import com.intellij.psi.PsiMethod;
26+
27+
public class MethoLookupElementFactory {
28+
29+
public static LookupElement create(PsiMethod method, String presentableMethod) {
30+
PsiClass containingClass = method.getContainingClass();
31+
return create(method, presentableMethod, containingClass == null ? null : containingClass.getName());
32+
}
33+
public static LookupElement create(PsiMethod method, String presentableMethod, String typeText) {
34+
LookupElementBuilder builder = LookupElementBuilder.create(method);
35+
builder = builder.withPresentableText(presentableMethod);
36+
builder = builder.withTypeText(typeText, true);
37+
builder = builder.withIcon(AllIcons.Nodes.Method);
38+
if (CamelIdeaUtils.getService().isAnnotatedWithHandler(method)) {
39+
//@Handle methods are marked with
40+
builder = builder.withBoldness(true);
41+
}
42+
if (method.isDeprecated()) {
43+
// mark as deprecated
44+
builder = builder.withStrikeoutness(true);
45+
}
46+
return builder.withAutoCompletionPolicy(AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE);
47+
}
48+
49+
}

0 commit comments

Comments
 (0)