-
Notifications
You must be signed in to change notification settings - Fork 20
🐛 Add integration test with real jdtls setup and fix a minor bug in method calls #198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| source.. = src/main/java/ | ||
| output.. = target/classes/ | ||
| bin.includes = META-INF/,\ | ||
| . | ||
| .,\ | ||
| projects/ |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,64 @@ | ||||||
| package io.konveyor.tackle.core.internal.symbol; | ||||||
|
|
||||||
| import static org.junit.Assert.assertFalse; | ||||||
| import static org.junit.Assert.assertTrue; | ||||||
|
|
||||||
| import java.util.List; | ||||||
|
|
||||||
| import org.eclipse.lsp4j.SymbolInformation; | ||||||
| import org.junit.Test; | ||||||
|
|
||||||
| import io.konveyor.tackle.core.internal.testing.AbstractSymbolProviderTest; | ||||||
|
|
||||||
|
|
||||||
| public class MethodCallSymbolProviderIntegrationTest extends AbstractSymbolProviderTest { | ||||||
|
|
||||||
| @Test | ||||||
| public void testFullyQualifiedMethodCalls() { | ||||||
| List<SymbolInformation> results = searchMethodCalls("io.konveyor.demo.PackageUsageExample.merge"); | ||||||
| results = inFile(results, "SampleApplication.java"); | ||||||
| printResults(results); | ||||||
| assertTrue("[1] Should find usage of merge() call in test-project/SampleApplication.java#callFullyQualifiedMethod()", | ||||||
| results.size() == 1); | ||||||
|
|
||||||
| List<SymbolInformation> entityManagerMergeResults = searchMethodCalls("javax.persistence.EntityManager.merge"); | ||||||
| entityManagerMergeResults = inFile(entityManagerMergeResults, "PackageUsageExample.java"); | ||||||
| printResults(entityManagerMergeResults); | ||||||
| assertTrue("[2] Should find usage of entityManager.merge() call in test-project/PackageUsageExample.java#merge()", | ||||||
| entityManagerMergeResults.size() == 1); | ||||||
|
|
||||||
| // Half qualified method call should not work | ||||||
| List<SymbolInformation> halfQualifiedResults = searchMethodCalls("PackageUsageExample.merge"); | ||||||
| printResults(halfQualifiedResults); | ||||||
| assertTrue("[3] Should not find any results matching PackageUsageExample.merge", | ||||||
| halfQualifiedResults.size() == 0); | ||||||
|
|
||||||
| // make sure patterns for fully qualified method calls work | ||||||
| List<SymbolInformation> mergeStarResults = searchMethodCalls("io.konveyor.demo.PackageUsageExample.merg*"); | ||||||
| printResults(mergeStarResults); | ||||||
| assertTrue("[4] Should find 1 result matching io.konveyor.demo.PackageUsageExample.merg*", | ||||||
| mergeStarResults.size() == 1); | ||||||
| } | ||||||
|
|
||||||
|
|
||||||
| @Test | ||||||
| public void testNonQualifiedMethodCalls() { | ||||||
| List<SymbolInformation> allResults = searchMethodCalls("merge"); | ||||||
|
|
||||||
| List<SymbolInformation> sampleAppResults = inFile(allResults, "SampleApplication.java"); | ||||||
| printResults(sampleAppResults); | ||||||
| assertTrue("[1] Should find usage of merge() call in test-project/SampleApplication.java#callFullyQualifiedMethod()", | ||||||
| sampleAppResults.size() == 1); | ||||||
|
|
||||||
| List<SymbolInformation> packageExampleResults = inFile(allResults, "PackageUsageExample.java"); | ||||||
| printResults(packageExampleResults); | ||||||
| assertTrue("[2] Should find usage of merge() call in test-project/PackageUsageExample.java#merge()", | ||||||
| packageExampleResults.size() == 1); | ||||||
|
|
||||||
| // make sure pattterns work | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix typo in comment. The comment has a typo: "pattterns" should be "patterns". 🔎 Proposed fix- // make sure pattterns work
+ // make sure patterns work📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| List<SymbolInformation> mergeStarResults = searchMethodCalls("merg*"); | ||||||
| printResults(mergeStarResults); | ||||||
| assertTrue("[3] Should find usage of merge() call in test-project/SampleApplication.java#callFullyQualifiedMethod() and test-project/PackageUsageExample.java#merge()", | ||||||
| mergeStarResults.size() == 2); | ||||||
| } | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| package io.konveyor.tackle.core.internal.symbol; | ||
|
|
||
| import static org.junit.Assert.assertTrue; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import org.eclipse.lsp4j.SymbolInformation; | ||
| import org.junit.Test; | ||
|
|
||
| import io.konveyor.tackle.core.internal.testing.AbstractSymbolProviderTest; | ||
|
|
||
|
|
||
| public class MethodDeclarationSymbolProviderIntegrationTest extends AbstractSymbolProviderTest { | ||
|
|
||
| @Test | ||
| public void testFullyQualifiedMethodDeclarations() { | ||
| // Test fully qualified method declaration search for SampleApplication.merge | ||
| List<SymbolInformation> sampleAppResults = searchMethodDeclarations("io.konveyor.demo.SampleApplication.merge"); | ||
| printResults(sampleAppResults); | ||
| assertTrue("[1] Should find merge() declaration in SampleApplication.java", | ||
| sampleAppResults.size() == 1); | ||
| assertTrue("[1b] Result should be in SampleApplication.java", | ||
| sampleAppResults.get(0).getLocation().getUri().contains("SampleApplication.java")); | ||
|
|
||
| // Test fully qualified method declaration search for PackageUsageExample.merge | ||
| List<SymbolInformation> packageExampleResults = searchMethodDeclarations("io.konveyor.demo.PackageUsageExample.merge"); | ||
| printResults(packageExampleResults); | ||
| assertTrue("[2] Should find merge() declaration in PackageUsageExample.java", | ||
| packageExampleResults.size() == 1); | ||
| assertTrue("[2b] Result should be in PackageUsageExample.java", | ||
| packageExampleResults.get(0).getLocation().getUri().contains("PackageUsageExample.java")); | ||
|
|
||
| // Test fully qualified method declaration search for ServletExample.merge | ||
| List<SymbolInformation> servletResults = searchMethodDeclarations("io.konveyor.demo.ServletExample.merge"); | ||
| printResults(servletResults); | ||
| assertTrue("[3] Should find merge() declaration in ServletExample.java", | ||
| servletResults.size() == 1); | ||
| assertTrue("[3b] Result should be in ServletExample.java", | ||
| servletResults.get(0).getLocation().getUri().contains("ServletExample.java")); | ||
|
|
||
| // Half qualified method declaration DOES work (different from method calls) | ||
| // This is because method declarations are matched by class name + method name | ||
| List<SymbolInformation> halfQualifiedResults = searchMethodDeclarations("SampleApplication.merge"); | ||
| printResults(halfQualifiedResults); | ||
| assertTrue("[4] Should find 1 result matching SampleApplication.merge (half-qualified works for declarations)", | ||
| halfQualifiedResults.size() == 1); | ||
| assertTrue("[4b] Result should be in SampleApplication.java", | ||
| halfQualifiedResults.get(0).getLocation().getUri().contains("SampleApplication.java")); | ||
|
|
||
| // Test pattern matching with wildcard on class name | ||
| List<SymbolInformation> patternResults = searchMethodDeclarations("io.konveyor.demo.*.merge"); | ||
| printResults(patternResults); | ||
| assertTrue("[5] Should find all 3 merge() declarations matching io.konveyor.demo.*.merge", | ||
| patternResults.size() == 3); | ||
| } | ||
|
|
||
|
|
||
| @Test | ||
| public void testNonQualifiedMethodDeclarations() { | ||
| // Search for all "merge" method declarations | ||
| List<SymbolInformation> allResults = searchMethodDeclarations("merge"); | ||
| printResults(allResults); | ||
|
|
||
| // Should find all 3 merge() declarations in the project | ||
| assertTrue("[1] Should find all 3 merge() declarations in the project", | ||
| allResults.size() == 3); | ||
|
|
||
| // Verify each file has exactly one merge() declaration | ||
| List<SymbolInformation> sampleAppResults = inFile(allResults, "SampleApplication.java"); | ||
| assertTrue("[2] Should find exactly 1 merge() declaration in SampleApplication.java", | ||
| sampleAppResults.size() == 1); | ||
|
|
||
| List<SymbolInformation> packageExampleResults = inFile(allResults, "PackageUsageExample.java"); | ||
| assertTrue("[3] Should find exactly 1 merge() declaration in PackageUsageExample.java", | ||
| packageExampleResults.size() == 1); | ||
|
|
||
| List<SymbolInformation> servletResults = inFile(allResults, "ServletExample.java"); | ||
| assertTrue("[4] Should find exactly 1 merge() declaration in ServletExample.java", | ||
| servletResults.size() == 1); | ||
|
|
||
| // Test pattern matching with wildcard | ||
| List<SymbolInformation> mergeStarResults = searchMethodDeclarations("merg*"); | ||
| printResults(mergeStarResults); | ||
| assertTrue("[5] Should find all 3 merge() declarations matching merg*", | ||
| mergeStarResults.size() == 3); | ||
| } | ||
|
|
||
|
|
||
| @Test | ||
| public void testMethodDeclarationPatterns() { | ||
| // Test various pattern combinations | ||
|
|
||
| // Pattern: method name ending with 'e' | ||
| List<SymbolInformation> mergeResults = searchMethodDeclarations("*merge"); | ||
| printResults(mergeResults); | ||
| assertTrue("[1] Should find all 3 merge() declarations matching *merge", | ||
| mergeResults.size() == 3); | ||
|
|
||
| // Test fully qualified pattern with class wildcard | ||
| List<SymbolInformation> demoPackageResults = searchMethodDeclarations("io.konveyor.demo.Sample*.merge"); | ||
| printResults(demoPackageResults); | ||
| assertTrue("[2] Should find merge() in SampleApplication matching io.konveyor.demo.Sample*.merge", | ||
| demoPackageResults.size() == 1); | ||
|
|
||
| // Test fully qualified pattern with method wildcard | ||
| List<SymbolInformation> sampleAllMethods = searchMethodDeclarations("io.konveyor.demo.SampleApplication.*"); | ||
| printResults(sampleAllMethods); | ||
| assertTrue("[3] Should find multiple method declarations in SampleApplication matching io.konveyor.demo.SampleApplication.*", | ||
| sampleAllMethods.size() > 1); | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logic error: second condition allows matches extending before the node.
The condition
(matchEnd == nodeEnd)on line 90 accepts matches that start before the node begins. For example, ifmatchStart = 10, matchEnd = 20andnodeStart = 15, nodeEnd = 20, the second condition evaluates totrueeven though the match extends outside the node's start boundary. This contradicts the comment stating "match falls within the node's range" and could cause incorrect nodes to be visited.🔎 Proposed fix
If the intent is to check whether the match is fully contained within the node:
Alternatively, if you need to handle overlapping boundaries where both start and end align:
Or if you need to check for any overlap between match and node ranges:
Please clarify the intended boundary semantics and adjust accordingly.
📝 Committable suggestion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@coderabbitai it is not possible to run into that situation as we will never have a method signature that encloses it container. is there a specific edge case you;re thinking of?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pranavgaikwad, the specific edge case I was concerned about was a scenario where
matchStart < nodeStartbutmatchEnd == nodeEnd(e.g., match starting at offset 10, node starting at 15, both ending at 20). In that case, the second condition would evaluate to true even though the match extends before the node's start boundary.However, I understand from your explanation that this won't occur in practice because of how JDT structures SearchMatch and AST nodes—the match won't extend outside its containing node's boundaries in this way. If that's based on your testing and understanding of JDT's behavior, then my concern doesn't apply, and the current logic is correct for your use case.
Thank you for the clarification! 🐰
🧠 Learnings used