Skip to content

Commit

Permalink
Micronaut: Code completion support for values of 'Mapping' annotation.
Browse files Browse the repository at this point in the history
  • Loading branch information
dbalek committed Jun 6, 2024
1 parent 66d637f commit f24ed12
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.micronaut.completion;

import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.processing.Completion;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import org.netbeans.modules.micronaut.db.Utils;

/**
*
* @author Dusan Balek
*/
public class MicronautJavaMappingPropertiesCompletion implements Processor {

private static final Set<String> supportedAnnotationTypes = Set.of("io.micronaut.context.annotation.Mapper.Mapping");
private Reference<ProcessingEnvironment> processingEnv;

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
return false;
}

@Override
public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
if (member != null && annotation != null) {
TypeMirror tm = element.asType();
if (tm.getKind() == TypeKind.EXECUTABLE) {
TypeMirror type = null;
switch (member.getSimpleName().toString()) {
case "from":
List<? extends TypeMirror> paramTypes = ((ExecutableType) tm).getParameterTypes();
if (paramTypes.size() == 1) {
type = paramTypes.get(0);
}
break;
case "to":
type = ((ExecutableType) tm).getReturnType();
break;
}
if (type != null && type.getKind() == TypeKind.DECLARED) {
TypeElement te = (TypeElement) ((DeclaredType) type).asElement();
if (Utils.getAnnotation(te.getAnnotationMirrors(), "io.micronaut.serde.annotation.Serdeable") != null) {
String format = "\"%s\"";
return ElementFilter.fieldsIn(te.getEnclosedElements()).stream().map(ve -> {
return new Completion() {
@Override
public String getValue() {
return String.format(format, ve.getSimpleName().toString());
}
@Override
public String getMessage() {
return null;
}
};
}).collect(Collectors.toList());
}
}
}
}
return Collections.emptyList();
}

@Override
public Set<String> getSupportedOptions() {
return Collections.emptySet();
}

@Override
public Set<String> getSupportedAnnotationTypes() {
return supportedAnnotationTypes;
}

@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}

@Override
public void init(ProcessingEnvironment processingEnv) {
this.processingEnv = new WeakReference<>(processingEnv);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ private static void fillJSON(CompilationInfo info, int level, String name, Varia
sb.append(" ");
}
if (name != null) {
sb.append('"').append(name).append("\":");
sb.append('"').append(name).append("\": ");
}
TypeMirror tm = ve.asType();
if (tm.getKind() == TypeKind.TYPEVAR) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<folder name="x-java">
<folder name="AnnotationProcessors">
<file name="org-netbeans-modules-micronaut-completion-MicronautJavaConfigPropertiesCompletion.instance"/>
<file name="org-netbeans-modules-micronaut-completion-MicronautJavaMappingPropertiesCompletion.instance"/>
</folder>
</folder>
<folder name="x-yaml">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,8 @@ public Completion createAttributeValueItem(CompilationInfo info, String value, S
if (ts.moveNext() && ts.offset() <= offset) {
switch (ts.token().id()) {
case STRING_LITERAL:
textEdit = new TextEdit(ts.offset(), offset, value);
int end = ts.offset() + ts.token().length() == offset + 1 ? offset + 1 : offset;
textEdit = new TextEdit(ts.offset(), end, value);
break;
case MULTILINE_STRING_LITERAL:
String[] tokenLines = ts.token().text().toString().split("\n");
Expand All @@ -651,7 +652,7 @@ public Completion createAttributeValueItem(CompilationInfo info, String value, S
}
}
Builder builder = CompletionCollector.newBuilder(label)
.kind(Completion.Kind.Text)
.kind(Completion.Kind.Value)
.sortText(value)
.insertTextFormat(Completion.TextFormat.PlainText)
.documentation(documentation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5107,7 +5107,7 @@ public void testAnnotationCompletion() throws Exception {
server.getTextDocumentService().didChange(new DidChangeTextDocumentParams(id, Arrays.asList(new TextDocumentContentChangeEvent(new Range(new Position(0, 19), new Position(0, 19)), 0, "alue=\"\""))));
completion = server.getTextDocumentService().completion(new CompletionParams(new TextDocumentIdentifier(toURI(src)), new Position(0, 25))).get();
actualItems = completion.getRight().getItems().stream().map(ci -> ci.getKind() + ":" + ci.getLabel()).collect(Collectors.toList());
assertTrue(actualItems.contains("Text:\"empty-statement\""));
assertTrue(actualItems.contains("Value:\"empty-statement\""));
}

interface Validator<T> {
Expand Down

0 comments on commit f24ed12

Please sign in to comment.