You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by db...@apache.org on 2022/03/09 07:42:47 UTC
[netbeans] branch master updated: SQL completion for Query annotations added. (#3722)
This is an automated email from the ASF dual-hosted git repository.
dbalek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push:
new 0bf3845 SQL completion for Query annotations added. (#3722)
0bf3845 is described below
commit 0bf384595621bae2b38c943d8face1198afa9831
Author: Dusan Balek <du...@oracle.com>
AuthorDate: Wed Mar 9 08:42:34 2022 +0100
SQL completion for Query annotations added. (#3722)
---
enterprise/micronaut/nbproject/project.xml | 8 +++
.../MicronautDataCompletionCollector.java | 8 +++
.../MicronautDataCompletionProvider.java | 5 ++
.../completion/MicronautDataCompletionTask.java | 81 +++++++++++++++++++---
ide/db.sql.editor/nbproject/project.properties | 2 +-
ide/db.sql.editor/nbproject/project.xml | 1 +
.../completion/ETCompletionContextResolver.java | 22 +++++-
.../nbcode/nbproject/platform.properties | 3 -
8 files changed, 114 insertions(+), 16 deletions(-)
diff --git a/enterprise/micronaut/nbproject/project.xml b/enterprise/micronaut/nbproject/project.xml
index e6d3c51..1cec8be 100644
--- a/enterprise/micronaut/nbproject/project.xml
+++ b/enterprise/micronaut/nbproject/project.xml
@@ -119,6 +119,14 @@
</run-dependency>
</dependency>
<dependency>
+ <code-name-base>org.netbeans.modules.db.sql.editor</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>1.53</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
<code-name-base>org.netbeans.modules.editor.codetemplates</code-name-base>
<build-prerequisite/>
<compile-dependency/>
diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautDataCompletionCollector.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautDataCompletionCollector.java
index 3f5abd0..34a0b1f 100644
--- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautDataCompletionCollector.java
+++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautDataCompletionCollector.java
@@ -22,6 +22,7 @@ import java.util.function.Consumer;
import javax.swing.text.Document;
import org.netbeans.api.editor.mimelookup.MimeRegistration;
import org.netbeans.api.lsp.Completion;
+import org.netbeans.spi.editor.completion.CompletionItem;
import org.netbeans.spi.lsp.CompletionCollector;
/**
@@ -47,6 +48,13 @@ public class MicronautDataCompletionCollector implements CompletionCollector {
public Completion createFinderMethodNameItem(String prefix, String name, int offset) {
return CompletionCollector.newBuilder(prefix + name).kind(Completion.Kind.Method).sortText(String.format("%04d%s", 10, name)).build();
}
+ @Override
+ public Completion createSQLItem(CompletionItem item) {
+ return CompletionCollector.newBuilder(item.getInsertPrefix().toString())
+ .insertText(item.getInsertPrefix().toString().replace("\"", "\\\""))
+ .kind(Completion.Kind.Property)
+ .build();
+ }
}).stream().forEach(consumer);
return true;
}
diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautDataCompletionProvider.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautDataCompletionProvider.java
index 074657f..867c54d 100644
--- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautDataCompletionProvider.java
+++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautDataCompletionProvider.java
@@ -95,6 +95,11 @@ public final class MicronautDataCompletionProvider implements CompletionProvider
.sortText(name)
.build();
}
+
+ @Override
+ public CompletionItem createSQLItem(CompletionItem item) {
+ return item;
+ }
}));
resultSet.setAnchorOffset(task.getAnchorOffset());
resultSet.finish();
diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautDataCompletionTask.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautDataCompletionTask.java
index 4bfda64..92d1160 100644
--- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautDataCompletionTask.java
+++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautDataCompletionTask.java
@@ -38,6 +38,7 @@ import java.util.prefs.PreferenceChangeListener;
import java.util.prefs.Preferences;
import java.util.regex.Pattern;
import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
@@ -46,7 +47,10 @@ import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Types;
+import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
+import javax.swing.text.StyledDocument;
+import org.netbeans.api.db.explorer.ConnectionManager;
import org.netbeans.api.editor.mimelookup.MimeLookup;
import org.netbeans.api.java.lexer.JavaTokenId;
import org.netbeans.api.java.source.CompilationController;
@@ -55,11 +59,16 @@ import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.TreeUtilities;
import org.netbeans.api.java.source.TypeUtilities;
import org.netbeans.api.lexer.TokenSequence;
+import org.netbeans.modules.db.sql.editor.api.completion.SQLCompletion;
+import org.netbeans.modules.db.sql.editor.api.completion.SQLCompletionContext;
+import org.netbeans.modules.db.sql.editor.api.completion.SQLCompletionResultSet;
import org.netbeans.modules.parsing.api.ParserManager;
import org.netbeans.modules.parsing.api.ResultIterator;
import org.netbeans.modules.parsing.api.Source;
import org.netbeans.modules.parsing.api.UserTask;
import org.netbeans.modules.parsing.spi.ParseException;
+import org.netbeans.spi.editor.completion.CompletionItem;
+import org.openide.text.NbDocument;
import org.openide.util.Exceptions;
import org.openide.util.WeakListeners;
@@ -69,8 +78,10 @@ import org.openide.util.WeakListeners;
*/
public class MicronautDataCompletionTask {
- private static final String REPOSITORY_ANNOTATION_NAME = "io.micronaut.data.annotation.Repository";
+ private static final String JPA_REPOSITORY_ANNOTATION_NAME = "io.micronaut.data.annotation.Repository";
+ private static final String JDBC_REPOSITORY_ANNOTATION_NAME = "io.micronaut.data.jdbc.annotation.JdbcRepository";
private static final String REPOSITORY_TYPE_NAME = "io.micronaut.data.repository.GenericRepository";
+ private static final String QUERY_ANNOTATION_TYPE_NAME = "io.micronaut.data.annotation.Query";
private static final String GET = "get";
private static final List<String> QUERY_PATTERNS = new ArrayList<>(Arrays.asList("find", "get", "query", "read", "retrieve", "search"));
private static final List<String> SPECIAL_QUERY_PATTERNS = new ArrayList<>(Arrays.asList("count", "countDistinct", "delete", "exists", "update"));
@@ -114,6 +125,7 @@ public class MicronautDataCompletionTask {
public static interface ItemFactory<T> {
T createFinderMethodItem(String name, String returnType, int offset);
T createFinderMethodNameItem(String prefix, String name, int offset);
+ T createSQLItem(CompletionItem item);
}
public <T> List<T> query(Document doc, int caretOffset, ItemFactory<T> factory) {
@@ -133,9 +145,15 @@ public class MicronautDataCompletionTask {
int len = anchorOffset - ts.offset();
if (len > 0 && ts.token().length() >= len) {
if (ts.token().id() == JavaTokenId.IDENTIFIER || ts.token().id().primaryCategory().startsWith("keyword") ||
- ts.token().id().primaryCategory().startsWith("string") || ts.token().id().primaryCategory().equals("literal")) {
+ ts.token().id().primaryCategory().equals("literal")) {
prefix = ts.token().text().toString().substring(0, len);
anchorOffset = ts.offset();
+ } else if (ts.token().id() == JavaTokenId.STRING_LITERAL) {
+ prefix = ts.token().text().toString().substring(1, ts.token().length() - 1);
+ anchorOffset = ts.offset() + 1;
+ } else if (ts.token().id() == JavaTokenId.MULTILINE_STRING_LITERAL) {
+ prefix = ts.token().text().toString().substring(3, len);
+ anchorOffset = ts.offset() + 3;
}
}
Consumer consumer = (namePrefix, name, type) -> {
@@ -147,12 +165,12 @@ public class MicronautDataCompletionTask {
switch (path.getLeaf().getKind()) {
case CLASS:
case INTERFACE:
- resolve(cc, path, prefix, true, consumer);
+ resolveFinderMethods(cc, path, prefix, true, consumer);
break;
case METHOD:
Tree returnType = ((MethodTree) path.getLeaf()).getReturnType();
if (returnType != null && findLastNonWhitespaceToken(ts, (int) sp.getEndPosition(path.getCompilationUnit(), returnType), anchorOffset) == null) {
- resolve(cc, path.getParentPath(), prefix, false, consumer);
+ resolveFinderMethods(cc, path.getParentPath(), prefix, false, consumer);
}
break;
case VARIABLE:
@@ -160,11 +178,17 @@ public class MicronautDataCompletionTask {
if (type != null && findLastNonWhitespaceToken(ts, (int) sp.getEndPosition(path.getCompilationUnit(), type), anchorOffset) == null) {
TreePath parentPath = path.getParentPath();
if (parentPath.getLeaf().getKind() == Tree.Kind.CLASS || parentPath.getLeaf().getKind() == Tree.Kind.INTERFACE) {
- resolve(cc, parentPath, prefix, false, consumer);
+ resolveFinderMethods(cc, parentPath, prefix, false, consumer);
}
}
break;
-
+ case STRING_LITERAL:
+ if (path.getParentPath().getLeaf().getKind() == Tree.Kind.ASSIGNMENT && path.getParentPath().getParentPath().getLeaf().getKind() == Tree.Kind.ANNOTATION) {
+ resolveQueryAnnotation(cc, path.getParentPath().getParentPath(), prefix, caretOffset - anchorOffset, item -> {
+ items.add(factory.createSQLItem(item));
+ });
+ }
+ break;
}
}
});
@@ -178,7 +202,43 @@ public class MicronautDataCompletionTask {
return anchorOffset;
}
- private <T> void resolve(CompilationController cc, TreePath path, String prefix, boolean full, Consumer consumer) throws IOException {
+ private <T> void resolveQueryAnnotation(CompilationController cc, TreePath path, String prefix, int off, java.util.function.Consumer<CompletionItem> consumer) throws IOException {
+ cc.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
+ Element el = cc.getTrees().getElement(path);
+ if (el instanceof TypeElement) {
+ if (QUERY_ANNOTATION_TYPE_NAME.contentEquals(((TypeElement) el).getQualifiedName())) {
+ TreePath clsPath = cc.getTreeUtilities().getPathElementOfKind(TreeUtilities.CLASS_TREE_KINDS, path);
+ if (clsPath != null && checkForRepositoryAnnotation(cc.getTrees().getElement(clsPath).getAnnotationMirrors(), false, new HashSet<>())) {
+ SQLCompletionContext ctx = SQLCompletionContext.empty()
+ .setStatement(prefix)
+ .setOffset(off)
+ .setDatabaseConnection(ConnectionManager.getDefault().getPreferredConnection(true));
+ SQLCompletion completion = SQLCompletion.create(ctx);
+ SQLCompletionResultSet resultSet = SQLCompletionResultSet.create();
+ completion.query(resultSet, (component, offset, text) -> {
+ final int caretOffset = component.getCaretPosition();
+ final StyledDocument document = (StyledDocument) component.getDocument();
+ try {
+ NbDocument.runAtomicAsUser(document, () -> {
+ try {
+ int documentOffset = anchorOffset + offset;
+ document.remove(documentOffset, caretOffset - documentOffset);
+ document.insertString(documentOffset, text.replace("\"", "\\\""), null);
+ } catch (BadLocationException ex) {
+ }
+ });
+ } catch (BadLocationException ex) {
+ }
+ });
+ for (CompletionItem item : resultSet.getItems()) {
+ consumer.accept(item);
+ }
+ }
+ }
+ }
+ }
+
+ private <T> void resolveFinderMethods(CompilationController cc, TreePath path, String prefix, boolean full, Consumer consumer) throws IOException {
cc.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
TypeUtilities tu = cc.getTypeUtilities();
TypeElement entity = getEntityFor(cc, path);
@@ -257,7 +317,7 @@ public class MicronautDataCompletionTask {
private static TypeElement getEntityFor(CompilationInfo info, TreePath path) {
TypeElement te = (TypeElement) info.getTrees().getElement(path);
if (te.getModifiers().contains(Modifier.ABSTRACT)) {
- if (checkForRepositoryAnnotation(te.getAnnotationMirrors(), new HashSet<>())) {
+ if (checkForRepositoryAnnotation(te.getAnnotationMirrors(), true, new HashSet<>())) {
Types types = info.getTypes();
TypeMirror repositoryType = types.erasure(info.getElements().getTypeElement(REPOSITORY_TYPE_NAME).asType());
for (TypeMirror iface : te.getInterfaces()) {
@@ -276,10 +336,11 @@ public class MicronautDataCompletionTask {
return null;
}
- private static boolean checkForRepositoryAnnotation(List<? extends AnnotationMirror> annotations, HashSet<TypeElement> checked) {
+ private static boolean checkForRepositoryAnnotation(List<? extends AnnotationMirror> annotations, boolean jpa, HashSet<TypeElement> checked) {
for (AnnotationMirror annotation : annotations) {
TypeElement annotationElement = (TypeElement) annotation.getAnnotationType().asElement();
- if (REPOSITORY_ANNOTATION_NAME.contentEquals(annotationElement.getQualifiedName()) || checked.add(annotationElement) && checkForRepositoryAnnotation(annotationElement.getAnnotationMirrors(), checked)) {
+ String repositoryAnnotationName = jpa ? JPA_REPOSITORY_ANNOTATION_NAME : JDBC_REPOSITORY_ANNOTATION_NAME;
+ if (repositoryAnnotationName.contentEquals(annotationElement.getQualifiedName()) || checked.add(annotationElement) && checkForRepositoryAnnotation(annotationElement.getAnnotationMirrors(), jpa, checked)) {
return true;
}
}
diff --git a/ide/db.sql.editor/nbproject/project.properties b/ide/db.sql.editor/nbproject/project.properties
index b2c7928..8cb5ace 100644
--- a/ide/db.sql.editor/nbproject/project.properties
+++ b/ide/db.sql.editor/nbproject/project.properties
@@ -17,7 +17,7 @@
javac.compilerargs=-Xlint -Xlint:-serial
javac.source=1.8
-spec.version.base=1.52.0
+spec.version.base=1.53.0
# org-netbeans-core: for /xml/lookups in the default fs
# (needed in order to load database connections from the SFS)
diff --git a/ide/db.sql.editor/nbproject/project.xml b/ide/db.sql.editor/nbproject/project.xml
index 90faa55..b171216 100644
--- a/ide/db.sql.editor/nbproject/project.xml
+++ b/ide/db.sql.editor/nbproject/project.xml
@@ -333,6 +333,7 @@
</test-dependencies>
<friend-packages>
<friend>com.sun.tools.odb</friend>
+ <friend>org.netbeans.modules.micronaut</friend>
<friend>org.netbeans.modules.php.editor</friend>
<package>org.netbeans.modules.db.sql.editor.api.completion</package>
</friend-packages>
diff --git a/java/j2ee.persistence/src/org/netbeans/modules/j2ee/persistence/editor/completion/ETCompletionContextResolver.java b/java/j2ee.persistence/src/org/netbeans/modules/j2ee/persistence/editor/completion/ETCompletionContextResolver.java
index f486719..d1f35e2 100644
--- a/java/j2ee.persistence/src/org/netbeans/modules/j2ee/persistence/editor/completion/ETCompletionContextResolver.java
+++ b/java/j2ee.persistence/src/org/netbeans/modules/j2ee/persistence/editor/completion/ETCompletionContextResolver.java
@@ -21,9 +21,13 @@ package org.netbeans.modules.j2ee.persistence.editor.completion;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
import javax.swing.text.BadLocationException;
import org.eclipse.persistence.jpa.jpql.parser.DefaultJPQLGrammar;
import org.eclipse.persistence.jpa.jpql.tools.ContentAssistProposals;
@@ -81,7 +85,10 @@ public class ETCompletionContextResolver implements CompletionContextResolver {
} else if("NamedQuery".equals(annotationName)){//NOI18N
completeJPQLContext(ctx, parsedNN, nnattr, result);
} else if("Query".equals(annotationName) && parsedNN.getAttributesList().size() == 1){//NOI18N
- completeJPQLContext(ctx, parsedNN, nnattr, result);
+ Element cls = ctx.getJavaClass();
+ if (cls == null || !checkForRepositoryAnnotation(cls.getAnnotationMirrors(), new HashSet<>())) {
+ completeJPQLContext(ctx, parsedNN, nnattr, result);
+ }
}
@@ -219,7 +226,18 @@ public class ETCompletionContextResolver implements CompletionContextResolver {
return false;
}
}
-
+
+ private static boolean checkForRepositoryAnnotation(List<? extends AnnotationMirror> annotations, HashSet<TypeElement> checked) {
+ for (AnnotationMirror annotation : annotations) {
+ TypeElement annotationElement = (TypeElement) annotation.getAnnotationType().asElement();
+ if (REPOSITORY_ANNOTATION_NAME.contentEquals(annotationElement.getQualifiedName()) || checked.add(annotationElement) && checkForRepositoryAnnotation(annotationElement.getAnnotationMirrors(), checked)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static final String REPOSITORY_ANNOTATION_NAME = "io.micronaut.data.jdbc.annotation.JdbcRepository";
private static final boolean DEBUG = Boolean.getBoolean("debug." + ETCompletionContextResolver.class.getName());
}
diff --git a/java/java.lsp.server/nbcode/nbproject/platform.properties b/java/java.lsp.server/nbcode/nbproject/platform.properties
index 870107f..15e5470 100644
--- a/java/java.lsp.server/nbcode/nbproject/platform.properties
+++ b/java/java.lsp.server/nbcode/nbproject/platform.properties
@@ -113,10 +113,7 @@ disabled.modules=\
org.netbeans.modules.css.prep,\
org.netbeans.modules.css.visual,\
org.netbeans.modules.db.kit,\
- org.netbeans.modules.db.core,\
- org.netbeans.modules.db.dataview,\
org.netbeans.modules.db.mysql,\
- org.netbeans.modules.db.sql.editor,\
org.netbeans.modules.db.sql.visualeditor,\
org.netbeans.modules.deadlock.detector,\
org.netbeans.modules.debugger.jpda.ant,\
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists