From 643849a6a525c69afdcc17196ded1601583ed073 Mon Sep 17 00:00:00 2001 From: Pranav Gaikwad Date: Wed, 27 Mar 2024 14:41:38 -0400 Subject: [PATCH 1/3] :bug: check accuracy of TypeReferenceMatch Signed-off-by: Pranav Gaikwad :update: Signed-off-by: Pranav Gaikwad --- .../SymbolInformationTypeRequestor.java | 24 ----- .../internal/symbol/TypeSymbolProvider.java | 87 +++++++++++++++++-- 2 files changed, 80 insertions(+), 31 deletions(-) diff --git a/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/SymbolInformationTypeRequestor.java b/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/SymbolInformationTypeRequestor.java index 8a1671c..6e99a6e 100644 --- a/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/SymbolInformationTypeRequestor.java +++ b/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/SymbolInformationTypeRequestor.java @@ -63,29 +63,6 @@ public void acceptSearchMatch(SearchMatch match) throws CoreException { } - var e = (IJavaElement) match.getElement(); - if (shouldCheckAccuracy(e)) { - - if ((!this.query.contains("?") && !this.query.contains("*")) && match.getAccuracy() == SearchMatch.A_INACCURATE) { - - //TODO: This is a hack, this will give use some clue of what we are looking at, if the search is exact then this should match - // I don't love this, but seems to be the right way - logInfo("attempting: " + e.getHandleIdentifier()); - // Adding specific case for annotations, they will always be inaccurrate. - if (!e.getHandleIdentifier().contains(query) && !(this.symbolKind == 4 || this.symbolKind == 5 || this.symbolKind == 1 || this.symbolKind == 3)) { - logInfo("exact match is looking for accurate results" + match); - return; - } - } - - if ((this.query.contains("?") && (this.query.contains("(") || this.query.contains(")"))) && match.getAccuracy() == SearchMatch.A_INACCURATE) { - if(!this.query.contains("*")) { - logInfo("exact match is looking for accurate results " + match); - return; - } - } - } - SymbolProvider symbolProvider = SymbolProviderResolver.resolve(this.symbolKind, match); if (symbolProvider instanceof WithQuery) { ((WithQuery) symbolProvider).setQuery(this.query); @@ -97,7 +74,6 @@ public void acceptSearchMatch(SearchMatch match) throws CoreException { logInfo("getting match: " + match + "with provider: " + symbolProvider); List symbols = Optional.ofNullable(symbolProvider.get(match)).orElse(new ArrayList<>()); this.symbols.addAll(symbols); - } public List getSymbols() { diff --git a/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/TypeSymbolProvider.java b/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/TypeSymbolProvider.java index 2109723..b985e40 100644 --- a/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/TypeSymbolProvider.java +++ b/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/TypeSymbolProvider.java @@ -5,27 +5,95 @@ import java.util.ArrayList; import java.util.List; +import org.eclipse.core.runtime.URIUtil; +import org.eclipse.jdt.core.IClassFile; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IImportDeclaration; import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IPackageDeclaration; import org.eclipse.jdt.core.search.SearchMatch; import org.eclipse.jdt.core.search.TypeDeclarationMatch; import org.eclipse.jdt.core.search.TypeParameterDeclarationMatch; import org.eclipse.jdt.core.search.TypeParameterReferenceMatch; import org.eclipse.jdt.core.search.TypeReferenceMatch; +import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.SymbolKind; -public class TypeSymbolProvider implements SymbolProvider { +public class TypeSymbolProvider implements SymbolProvider, WithQuery { + private String query; + @Override public List get(SearchMatch match) { SymbolKind k = convertSymbolKind((IJavaElement) match.getElement()); List symbols = new ArrayList<>(); // For Method Calls we will need to do the local variable trick - if (!(match instanceof TypeReferenceMatch || - match instanceof TypeDeclarationMatch || - match instanceof TypeParameterDeclarationMatch || - match instanceof TypeParameterReferenceMatch)) { - return null; + if (!(match instanceof TypeReferenceMatch || + match instanceof TypeDeclarationMatch || + match instanceof TypeParameterDeclarationMatch || + match instanceof TypeParameterReferenceMatch)) { + return null; + } + // TypeReferenceMatch often are inaccurate in that if a pattern is a.b.C we get + // matches for references of C no matter whether they are in package a.b or not + // we try to confirm whether C we are getting belongs to package a.b with checks: + // first, we check if the file belongs to package a.b + // second, we check if CompilationUnit has package declaration of a.b + // third, we check if CompilationUnit has explicit import of a.b.C or a.b.* + if (match instanceof TypeReferenceMatch && this.query.contains(".")) { + try { + String qualification = ""; + int dotIndex = this.query.lastIndexOf('.'); + if (dotIndex > 0) { + qualification = this.query.substring(0, dotIndex); + } + var element = (IJavaElement) match.getElement(); + ICompilationUnit compilationUnit = (ICompilationUnit) element + .getAncestor(IJavaElement.COMPILATION_UNIT); + if (compilationUnit == null) { + IClassFile cls = (IClassFile) element.getAncestor(IJavaElement.CLASS_FILE); + if (cls != null) { + // TODO: make sure following doesn't affect performance + compilationUnit = cls.becomeWorkingCopy(null, null, null); + } + } + boolean isAccurate = false; + Location location = getLocation((IJavaElement) match.getElement(), match); + // if the file is in the same package as the query + // there's a high chance its an accurate match + if (qualification != "" && location.getUri().contains(qualification.replaceAll(".", "/"))) { + isAccurate = true; + } + if (compilationUnit != null && !isAccurate) { + // if the file contains package declaration that matches the query, then type + // can be referenced without its fully qualified name + for (IPackageDeclaration packageDecl : compilationUnit.getPackageDeclarations()) { + if (qualification != "" && packageDecl.getElementName().matches(qualification)) { + isAccurate = true; + } + } + // if the file contains explicit imports for the fully qualified name + // or a .* import with partial qualified name then type must be accurate + if (isAccurate) { + for (IImportDeclaration importDecl : compilationUnit.getImports()) { + String importElement = importDecl.getElementName(); + if (importElement.matches(this.query)) { + isAccurate = true; + } + if (qualification != "" && + importElement.replaceAll(".*", "").matches(qualification)) { + isAccurate = true; + } + } + } + } + if (!isAccurate) { + return null; + } + } catch (Exception e) { + logInfo("failed to determine accuracy of TypeReferenceMatch accepting.." + match); } + } try { var mod = (IJavaElement) match.getElement(); SymbolInformation symbol = new SymbolInformation(); @@ -34,7 +102,6 @@ public List get(SearchMatch match) { symbol.setContainerName(mod.getParent().getElementName()); symbol.setLocation(getLocation((IJavaElement) match.getElement(), match)); symbols.add(symbol); - } catch (Exception e) { logInfo("Unable to convert for TypeSymbolProvider: " + e); @@ -43,4 +110,10 @@ public List get(SearchMatch match) { return symbols; } + + @Override + public void setQuery(String query) { + // TODO Auto-generated method stub + this.query = query; + } } From 7bcb27e9d30a723bfe191dd0779f6518ff8ff14c Mon Sep 17 00:00:00 2001 From: Pranav Gaikwad Date: Wed, 27 Mar 2024 20:28:50 -0400 Subject: [PATCH 2/3] :bug: fix accuracy of method call searches Signed-off-by: Pranav Gaikwad --- .../core/internal/SampleDelegateCommandHandler.java | 5 ++++- .../internal/symbol/MethodCallSymbolProvider.java | 12 ++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/SampleDelegateCommandHandler.java b/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/SampleDelegateCommandHandler.java index a4b3638..7d2d96e 100644 --- a/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/SampleDelegateCommandHandler.java +++ b/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/SampleDelegateCommandHandler.java @@ -123,7 +123,10 @@ private static SearchPattern getPatternSingleQuery(int location, String query) t case 7: case 9: return SearchPattern.createPattern(query, IJavaSearchConstants.TYPE, IJavaSearchConstants.REFERENCES, pattern); - case 2: + case 2: + if (query.contains(".")) { + return SearchPattern.createPattern(query, IJavaSearchConstants.METHOD, IJavaSearchConstants.QUALIFIED_REFERENCE, SearchPattern.R_PATTERN_MATCH | SearchPattern.R_ERASURE_MATCH); + } // Switched back to referenced return SearchPattern.createPattern(query, IJavaSearchConstants.METHOD, IJavaSearchConstants.REFERENCES, SearchPattern.R_PATTERN_MATCH | SearchPattern.R_ERASURE_MATCH); case 3: diff --git a/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/MethodCallSymbolProvider.java b/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/MethodCallSymbolProvider.java index 9d90745..7e62ac0 100644 --- a/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/MethodCallSymbolProvider.java +++ b/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/MethodCallSymbolProvider.java @@ -7,6 +7,8 @@ import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.search.MethodReferenceMatch; import org.eclipse.jdt.core.search.SearchMatch; import org.eclipse.lsp4j.SymbolInformation; @@ -22,16 +24,6 @@ public List get(SearchMatch match) { // For Method Calls we will need to do the local variable trick try { MethodReferenceMatch m = (MethodReferenceMatch) match; - - // Default to filter to only accurate matches - var filterOut = m.getAccuracy() != SearchMatch.A_ACCURATE; - if (query.contains("*")) { - filterOut = false; - } - - if (filterOut) { - return symbols; - } IMethod e = (IMethod) m.getElement(); SymbolInformation symbol = new SymbolInformation(); symbol.setName(e.getElementName()); From 4fa8b8c410053c016041594b7bce5216ba7e6801 Mon Sep 17 00:00:00 2001 From: Pranav Gaikwad Date: Thu, 28 Mar 2024 12:24:59 -0400 Subject: [PATCH 3/3] :bug: minor fix Signed-off-by: Pranav Gaikwad --- .../tackle/core/internal/symbol/TypeSymbolProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/TypeSymbolProvider.java b/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/TypeSymbolProvider.java index b985e40..a226cbd 100644 --- a/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/TypeSymbolProvider.java +++ b/java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/TypeSymbolProvider.java @@ -74,7 +74,7 @@ public List get(SearchMatch match) { } // if the file contains explicit imports for the fully qualified name // or a .* import with partial qualified name then type must be accurate - if (isAccurate) { + if (!isAccurate) { for (IImportDeclaration importDecl : compilationUnit.getImports()) { String importElement = importDecl.getElementName(); if (importElement.matches(this.query)) {