Skip to content

Commit

Permalink
Merge pull request apache#7316 from dbalek/dbalek/micronaut-expr-lang…
Browse files Browse the repository at this point in the history
…-fix

Micronaut: Method parameters should be resolvable in expression language
  • Loading branch information
dbalek authored Apr 23, 2024
2 parents f01e76e + bfc6a19 commit c23dbb6
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 38 deletions.
2 changes: 1 addition & 1 deletion enterprise/micronaut/nbproject/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>2.49</specification-version>
<specification-version>2.68</specification-version>
</run-dependency>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
*/
public class MicronautConfigUtilities {

private static final Pattern REGEXP = Pattern.compile("^(application|bootstrap)(-\\w*)*\\.(yml|properties)$", Pattern.CASE_INSENSITIVE);
private static final Pattern REGEXP = Pattern.compile("^(application|bootstrap)(-\\w*)*\\.(yml|yaml|properties)$", Pattern.CASE_INSENSITIVE);

public static final String YAML_MIME = "text/x-yaml";
public static final String PROPERTIES_MIME = "text/x-properties";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,14 @@ public Completion createJavaElementItem(CompilationInfo info, Element element, i
}
Builder builder = CompletionCollector.newBuilder(simpleName);
switch (element.getKind()) {
case PARAMETER:
builder.kind(Completion.Kind.Variable).sortText(String.format("%04d%s", 90, simpleName))
.labelDescription(Utils.getTypeName(info, element.asType(), false, false).toString());
break;
case RECORD_COMPONENT:
builder.kind(Completion.Kind.Field).sortText(String.format("%04d%s", 90, simpleName))
.labelDescription(Utils.getTypeName(info, element.asType(), false, false).toString());
break;
case ENUM:
builder.kind(Completion.Kind.Enum).sortText(String.format("%04d%s", 300, simpleName));
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,16 @@ private static class MicronautDataCompletionQuery extends AsyncCompletionQuery {
private static final String RECORD_ICON = "org/netbeans/modules/editor/resources/completion/record.png";
private static final String METHOD_PUBLIC = "org/netbeans/modules/editor/resources/completion/method_16.png"; //NOI18N
private static final String METHOD_ST_PUBLIC = "org/netbeans/modules/editor/resources/completion/method_static_16.png";
private static final String FIELD_PUBLIC = "org/netbeans/modules/editor/resources/completion/field_16.png"; //NOI18N
private static final String LOCAL_VARIABLE = "org/netbeans/modules/editor/resources/completion/localVariable.gif"; //NOI18N
private static final String ATTRIBUTE_VALUE = "org/netbeans/modules/java/editor/resources/attribute_value_16.png"; // NOI18N
private static final String PROPERTY = "org/netbeans/modules/beans/resources/propertyRO.gif";
private static final String KEYWORD_COLOR = getHTMLColor(64, 64, 217);
private static final String PACKAGE_COLOR = getHTMLColor(64, 150, 64);
private static final String CLASS_COLOR = getHTMLColor(150, 64, 64);
private static final String INTERFACE_COLOR = getHTMLColor(128, 128, 128);
private static final String FIELD_COLOR = getHTMLColor(64, 198, 88);
private static final String PARAMETER_COLOR = getHTMLColor(64, 64, 188);
private static final String PARAMETERS_COLOR = getHTMLColor(192, 192, 192);
private static final String PARAMETER_NAME_COLOR = getHTMLColor(224, 160, 65);
private static final String ATTRIBUTE_VALUE_COLOR = getHTMLColor(128, 128, 128);
Expand Down Expand Up @@ -496,6 +500,14 @@ public CompletionItem createJavaElementItem(CompilationInfo info, Element elemen
}
CompletionUtilities.CompletionItemBuilder builder = CompletionUtilities.newCompletionItemBuilder(simpleName).startOffset(offset);
switch (element.getKind()) {
case PARAMETER:
builder.iconResource(LOCAL_VARIABLE).leftHtmlText(PARAMETER_COLOR + simpleName + COLOR_END).sortPriority(90)
.rightHtmlText(Utils.getTypeName(info, element.asType(), false, false).toString());
break;
case RECORD_COMPONENT:
builder.iconResource(FIELD_PUBLIC).leftHtmlText(FIELD_COLOR + simpleName + COLOR_END).sortPriority(90)
.rightHtmlText(Utils.getTypeName(info, element.asType(), false, false).toString());
break;
case ENUM:
builder.iconResource(ENUM_ICON).leftHtmlText(CLASS_COLOR + simpleName + COLOR_END).sortPriority(300);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public <T> Result<T> query(int offset, ItemFactory<T> factory) {
if (tree == null) {
kws = ctx.getScope().getEnclosingMethod() != null ? Arrays.asList("true", "false", "null", "this", "empty", "not") : Arrays.asList("true", "false", "null", "empty", "not");
builtins = Arrays.asList("T", "()", "ctx", "[]", "env", "[]");
elements = ctx.getContextMethods();
elements = ctx.getContextElements();
anchorOffset = startOffset + offset;
} else {
String tokenText = ts.token().text().subSequence(0, offset - ts.offset()).toString().trim();
Expand All @@ -105,7 +105,7 @@ public <T> Result<T> query(int offset, ItemFactory<T> factory) {
if (offset <= tree.getStartPosition()) {
kws = ctx.getScope().getEnclosingMethod() != null ? Arrays.asList("true", "false", "null", "this", "empty", "not") : Arrays.asList("true", "false", "null", "empty", "not");
builtins = Arrays.asList("T", "()", "ctx", "[]", "env", "[]");
elements = ctx.getContextMethods();
elements = ctx.getContextElements();
} else {
ExpressionTree lastTree = tree;
if (tree.getKind() == ExpressionTree.Kind.ERRONEOUS) {
Expand Down Expand Up @@ -149,7 +149,7 @@ public <T> Result<T> query(int offset, ItemFactory<T> factory) {
case NONE:
String prev = prevNonWSTokenText(prefix);
if ("#".equals(prev)) {
elements = ctx.getContextMethods();
elements = ctx.getContextElements();
}
break;
}
Expand Down Expand Up @@ -214,7 +214,7 @@ public <T> Result<T> query(int offset, ItemFactory<T> factory) {
kws = Arrays.asList("this");
}
builtins = Arrays.asList("T", "()", "ctx", "[]", "env", "[]");
elements = ctx.getContextMethods();
elements = ctx.getContextElements();
}
break;
case EQUAL_TO:
Expand All @@ -225,7 +225,7 @@ public <T> Result<T> query(int offset, ItemFactory<T> factory) {
} else {
kws = ctx.getScope().getEnclosingMethod() != null ? Arrays.asList("null", "this"): Arrays.asList("null");
builtins = Arrays.asList("T", "()", "ctx", "[]", "env", "[]");
elements = ctx.getContextMethods();
elements = ctx.getContextElements();
}
break;
case AND:
Expand All @@ -238,11 +238,11 @@ public <T> Result<T> query(int offset, ItemFactory<T> factory) {
case NOT:
kws = ctx.getScope().getEnclosingMethod() != null ? Arrays.asList("true", "false", "not", "empty", "this"): Arrays.asList("true", "false", "not", "empty");
builtins = Arrays.asList("T", "()", "ctx", "[]", "env", "[]");
elements = ctx.getContextMethods();
elements = ctx.getContextElements();
break;
case EMPTY:
builtins = Arrays.asList("T", "()", "ctx", "[]", "env", "[]");
elements = ctx.getContextMethods();
elements = ctx.getContextElements();
break;
case INSTANCE_OF:
ExpressionTree.InstanceOf instanceOf = (ExpressionTree.InstanceOf) path.getLeaf();
Expand All @@ -262,7 +262,7 @@ public <T> Result<T> query(int offset, ItemFactory<T> factory) {
if ("?". equals(prev) || ":".equals(prev)) {
kws = ctx.getScope().getEnclosingMethod() != null ? Arrays.asList("true", "false", "null", "this", "empty", "not") : Arrays.asList("true", "false", "null", "empty", "not");
builtins = Arrays.asList("T", "()", "ctx", "[]", "env", "[]");
elements = ctx.getContextMethods();
elements = ctx.getContextElements();
}
}
break;
Expand All @@ -274,12 +274,12 @@ public <T> Result<T> query(int offset, ItemFactory<T> factory) {
if (callee != null) {
TypeMirror pacTM = callee.getTypeMirror(ctx);
if (pacTM.getKind() == TypeKind.DECLARED) {
elements = ElementFilter.methodsIn(((DeclaredType) pacTM).asElement().getEnclosedElements()).stream()
elements = ((DeclaredType) pacTM).asElement().getEnclosedElements().stream()
.filter(ee -> callee.getKind() != ExpressionTree.Kind.TYPE_REFERENCE || ee.getModifiers().contains(Modifier.STATIC))
.collect(Collectors.toList());
}
} else {
elements = ctx.getContextMethods();
elements = ctx.getContextElements();
}
}
break;
Expand All @@ -296,12 +296,12 @@ public <T> Result<T> query(int offset, ItemFactory<T> factory) {
.collect(Collectors.toList());
}
} else {
elements = ctx.getContextMethods();
elements = ctx.getContextElements();
}
} else if ("(".equals(prev) || ",".equals(prev)) {
kws = ctx.getScope().getEnclosingMethod() != null ? Arrays.asList("true", "false", "null", "this", "empty", "not") : Arrays.asList("true", "false", "null", "empty", "not");
builtins = Arrays.asList("T", "()", "ctx", "[]", "env", "[]");
elements = ctx.getContextMethods();
elements = ctx.getContextElements();
}
break;
}
Expand Down Expand Up @@ -381,7 +381,16 @@ public <T> Result<T> query(int offset, ItemFactory<T> factory) {
items.add(factory.createBeanPropertyItem(propertyName, returnType, anchorOffset));
}
}
} else {
} else if (element.getKind() == ElementKind.RECORD_COMPONENT) {
TypeMirror enclType = element.getEnclosingElement().asType();
if (enclType.getKind() == TypeKind.DECLARED && Utils.startsWith(name, prefix) && info.getTrees().isAccessible(ctx.getScope(), element, (DeclaredType) enclType)) {
items.add(factory.createJavaElementItem(info, element, anchorOffset));
}
} else if (element.getKind() == ElementKind.PARAMETER) {
if (Utils.startsWith(name, prefix)) {
items.add(factory.createJavaElementItem(info, element, anchorOffset));
}
} else if (element.getKind().isClass() || element.getKind().isInterface()) {
if (Utils.startsWith(name, prefix) && info.getTrees().isAccessible(ctx.getScope(), (TypeElement) element)) {
items.add(factory.createJavaElementItem(info, element, anchorOffset));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,19 @@ public Scope getScope() {
return scope;
}

public List<ExecutableElement> getContextMethods() {
public List<? extends Element> getContextElements() {
if (contextClasses == null) {
initializeContextClasses();
}
List<ExecutableElement> methods = new ArrayList<>();
List<Element> elements = new ArrayList<>();
for (TypeElement contextClass : contextClasses) {
methods.addAll(ElementFilter.methodsIn(contextClass.getEnclosedElements()));
elements.addAll(ElementFilter.methodsIn(contextClass.getEnclosedElements()));
}
return methods;
ExecutableElement enclosingMethod = scope.getEnclosingMethod();
if (enclosingMethod != null && !enclosingMethod.getParameters().isEmpty()) {
elements.addAll(enclosingMethod.getParameters());
}
return elements;
}

private void initializeContextClasses() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.List;
import java.util.stream.Collectors;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
Expand Down Expand Up @@ -564,20 +565,20 @@ public <R, D> R accept(Scanner<R, D> scanner, D data) {

@Override
protected void resolve(EvaluationContext ctx) {
List<ExecutableElement> methods = null;
List<? extends Element> elements = null;
DeclaredType dt = null;
if (callee == null) {
methods = ctx.getContextMethods();
elements = ctx.getContextElements();
} else {
TypeMirror calleeTM = callee.getTypeMirror(ctx);
if (calleeTM.getKind() == TypeKind.DECLARED) {
dt = (DeclaredType) calleeTM;
methods = ElementFilter.methodsIn(((TypeElement) dt.asElement()).getEnclosedElements());
elements = ((TypeElement) dt.asElement()).getEnclosedElements();
}
}
if (methods != null && !methods.isEmpty()) {
if (elements != null && !elements.isEmpty()) {
List<TypeMirror> argTypes = arguments.stream().map(arg -> arg.getTypeMirror(ctx)).collect(Collectors.toList());
for (ExecutableElement ee : methods) {
for (ExecutableElement ee : ElementFilter.methodsIn(elements)) {
TypeMirror enclType = dt != null ? dt : ee.getEnclosingElement().asType();
if (enclType.getKind() == TypeKind.DECLARED && identifier.contentEquals(ee.getSimpleName()) && ctx.getTrees().isAccessible(ctx.getScope(), ee, (DeclaredType) enclType)) {
ExecutableType et = (ExecutableType) ctx.getTypes().asMemberOf((DeclaredType) enclType, ee);
Expand Down Expand Up @@ -656,25 +657,40 @@ public <R, D> R accept(Scanner<R, D> scanner, D data) {

@Override
protected void resolve(EvaluationContext ctx) {
List<ExecutableElement> methods = null;
List<? extends Element> elements = null;
DeclaredType dt = null;
if (callee == null) {
methods = ctx.getContextMethods();
elements = ctx.getContextElements();
} else {
TypeMirror calleeTM = callee.getTypeMirror(ctx);
if (calleeTM.getKind() == TypeKind.DECLARED) {
dt = (DeclaredType) calleeTM;
methods = ElementFilter.methodsIn(((TypeElement) dt.asElement()).getEnclosedElements());
elements = ((TypeElement) dt.asElement()).getEnclosedElements();
}
}
if (methods != null && !methods.isEmpty()) {
for (ExecutableElement ee : methods) {
TypeMirror enclType = dt != null ? dt : ee.getEnclosingElement().asType();
if (enclType.getKind() == TypeKind.DECLARED && identifier.equals(getPropertyName(ee)) && ctx.getTrees().isAccessible(ctx.getScope(), ee, (DeclaredType) enclType)) {
ExecutableType et = (ExecutableType) ctx.getTypes().asMemberOf((DeclaredType) enclType, ee);
element = ee;
typeMirror = et.getReturnType();
return;
if (elements != null && !elements.isEmpty()) {
for (Element e : elements) {
if (e.getKind() == ElementKind.METHOD) {
TypeMirror enclType = dt != null ? dt : e.getEnclosingElement().asType();
if (enclType.getKind() == TypeKind.DECLARED && identifier.equals(getPropertyName((ExecutableElement) e)) && ctx.getTrees().isAccessible(ctx.getScope(), e, (DeclaredType) enclType)) {
ExecutableType et = (ExecutableType) ctx.getTypes().asMemberOf((DeclaredType) enclType, e);
element = e;
typeMirror = et.getReturnType();
return;
}
} else if (e.getKind() == ElementKind.RECORD_COMPONENT) {
TypeMirror enclType = dt != null ? dt : e.getEnclosingElement().asType();
if (enclType.getKind() == TypeKind.DECLARED && identifier.contentEquals(e.getSimpleName()) && ctx.getTrees().isAccessible(ctx.getScope(), e, (DeclaredType) enclType)) {
element = e;
typeMirror = e.asType();
return;
}
} else if (e.getKind() == ElementKind.PARAMETER) {
if (identifier.contentEquals(e.getSimpleName())) {
element = e;
typeMirror = e.asType();
return;
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion java/java.lsp.server/vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,7 @@ function doActivateWithJDK(specifiedJDK: string | null, context: ExtensionContex
const conf = workspace.getConfiguration();
let documentSelectors : DocumentSelector = [
{ language: 'java' },
{ language: 'yaml', pattern: '**/{application,bootstrap}*.yml' },
{ language: 'yaml', pattern: '**/{application,bootstrap}*.{yml,yaml}' },
{ language: 'properties', pattern: '**/{application,bootstrap}*.properties' },
{ language: 'jackpot-hint' },
{ language: 'xml', pattern: '**/pom.xml' },
Expand Down
2 changes: 1 addition & 1 deletion java/java.source.base/nbproject/project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ javadoc.name=Java Source Base
javadoc.title=Java Source Base
javadoc.arch=${basedir}/arch.xml
javadoc.apichanges=${basedir}/apichanges.xml
spec.version.base=2.67.0
spec.version.base=2.68.0
test.qa-functional.cp.extra=${refactoring.java.dir}/modules/ext/nb-javac-api.jar
test.unit.run.cp.extra=${o.n.core.dir}/core/core.jar:\
${o.n.core.dir}/lib/boot.jar:\
Expand Down
Loading

0 comments on commit c23dbb6

Please sign in to comment.