diff options
author | Stephan Herrmann | 2019-08-20 20:45:09 +0000 |
---|---|---|
committer | Stephan Herrmann | 2019-10-06 18:31:07 +0000 |
commit | de3ca7b4dbfafe1f98955d1c839f4652973fb406 (patch) | |
tree | 6267415bc9cb27f2ab1f066d2d9802497f823c48 | |
parent | 33f5b5f615926308947076f2bb0c71a1e038d04f (diff) | |
download | eclipse.jdt.core-de3ca7b4dbfafe1f98955d1c839f4652973fb406.tar.gz eclipse.jdt.core-de3ca7b4dbfafe1f98955d1c839f4652973fb406.tar.xz eclipse.jdt.core-de3ca7b4dbfafe1f98955d1c839f4652973fb406.zip |
Bug 285379 - [content assist] infinite loop
- patch originally from Satyam
Change-Id: If7cb213e5fa199a6744269452a6d6fe8a6437c88
6 files changed, 153 insertions, 1 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java index 304d2120df..b5300fad77 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java @@ -43,7 +43,7 @@ import org.eclipse.jdt.internal.core.eval.EvaluationContextWrapper; public class CompletionTests extends AbstractJavaModelCompletionTests { static { -// TESTS_NAMES = new String[] { "testCompletionMethodDeclaration17"}; + TESTS_NAMES = new String[] { "test285379"}; } public static Test suite() { return buildModelTestSuite(CompletionTests.class, BYTECODE_DECLARATION_ORDER); @@ -20584,6 +20584,66 @@ public void test270437c() throws JavaModelException { requestor.getResults()); } +/* + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=285379 + */ +public void test285379a() throws JavaModelException { + CompletionTestsRequestor requestor = new CompletionTestsRequestor(); + ICompilationUnit cu= getCompilationUnit("Completion", "src", "", "Completion285379.java"); + + String str = cu.getSource(); + String completeBehind = "pkgtest285379.X1."; + int cursorLocation = str.indexOf(completeBehind) + completeBehind.length(); + cu.codeComplete(cursorLocation, requestor); + + // just not hang... +} + +/* + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=285379 + */ +public void test285379b() throws JavaModelException { + CompletionTestsRequestor requestor = new CompletionTestsRequestor(); + ICompilationUnit cu= getCompilationUnit("Completion", "src", "", "Completion285379.java"); + + String str = cu.getSource(); + String completeBehind = "return "; + int cursorLocation = str.indexOf(completeBehind) + completeBehind.length(); + cu.codeComplete(cursorLocation, requestor); + + // just not hang... +} + +/* + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=285379 + */ +public void test285379c() throws JavaModelException { + CompletionTestsRequestor requestor = new CompletionTestsRequestor(); + ICompilationUnit cu= getCompilationUnit("Completion", "src", "", "Completion285379.java"); + + String str = cu.getSource(); + String completeBehind = "equals"; + int cursorLocation = str.indexOf(completeBehind) + completeBehind.length(); + cu.codeComplete(cursorLocation, requestor); + + // just not hang... +} + +/* + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=285379 + */ +public void test285379d() throws JavaModelException { + CompletionTestsRequestor requestor = new CompletionTestsRequestor(); + ICompilationUnit cu= getCompilationUnit("Completion", "src", "", "Completion285379.java"); + + String str = cu.getSource(); + String completeBehind = "(var"; + int cursorLocation = str.indexOf(completeBehind) + completeBehind.length(); + cu.codeComplete(cursorLocation, requestor); + + // just not hang... +} + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=270436 public void test270436a() throws JavaModelException { // This test is to ensure that an interface is not offered as a choice when expecting a class. diff --git a/org.eclipse.jdt.core.tests.model/workspace/Completion/.classpath b/org.eclipse.jdt.core.tests.model/workspace/Completion/.classpath index f1fe1cfc51..af46168d37 100644 --- a/org.eclipse.jdt.core.tests.model/workspace/Completion/.classpath +++ b/org.eclipse.jdt.core.tests.model/workspace/Completion/.classpath @@ -11,6 +11,7 @@ <classpathentry kind="lib" path="constructors.jar" sourcepath="/Completion/constructorssrc.zip"/> <classpathentry kind="lib" path="generics.jar" sourcepath="/Completion/genericssrc.zip"/> <classpathentry kind="lib" path="bug185318.jar"/> + <classpathentry kind="lib" path="test285379.jar"/> <classpathentry kind="lib" path="class-folder"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/org.eclipse.jdt.core.tests.model/workspace/Completion/src/Completion285379.java b/org.eclipse.jdt.core.tests.model/workspace/Completion/src/Completion285379.java new file mode 100644 index 0000000000..53d98a004d --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Completion/src/Completion285379.java @@ -0,0 +1,26 @@ +import pkgtest285379.X1; +public class Completion285379 extends X1{ + public interface testI{ + void fooI(); + }; + X1 testVar; + Object o; + public static testI foo() + { + X1 a; + return + } + public void foo1() + { + pkgtest285379.X1. + } + public boolean foo2(X1 var) + { + if (var.equals(testVar)) + return; + } + void bar(String var) { + X1 x; + x.equals(var); + } +} diff --git a/org.eclipse.jdt.core.tests.model/workspace/Completion/test285379.jar b/org.eclipse.jdt.core.tests.model/workspace/Completion/test285379.jar Binary files differnew file mode 100644 index 0000000000..9c0a6477e6 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Completion/test285379.jar diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index e31e319b7f..03e6df4e54 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -1608,6 +1608,10 @@ public MethodBinding[] methods() { this.tagBits |= TagBits.AreMethodsComplete; return this.methods; } +@Override +public void setHierarchyCheckDone() { + this.tagBits |= TagBits.BeginHierarchyCheck | TagBits.EndHierarchyCheck; +} @Override public TypeBinding prototype() { @@ -2095,8 +2099,60 @@ public ReferenceBinding superclass() { this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits); if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) // avoid the side-effects of hasTypeBit()! this.typeBits |= applyCloseableClassWhitelists(); + detectCircularHierarchy(); return this.superclass; } + +private void breakLoop() { + ReferenceBinding currentSuper = this.superclass; + ReferenceBinding prevSuper = null; + while (currentSuper != null) { + if ((currentSuper.tagBits & TagBits.EndHierarchyCheck) != 0 && prevSuper instanceof BinaryTypeBinding) { + ((BinaryTypeBinding)prevSuper).superclass = this.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); + break; + } + currentSuper.tagBits |= TagBits.EndHierarchyCheck; + prevSuper = currentSuper; + currentSuper = currentSuper.superclass(); + } +} + +private void detectCircularHierarchy() { + ReferenceBinding currentSuper = this.superclass; + ReferenceBinding tempSuper = null; + int count = 0; + int skipCount = 20; + while (currentSuper != null) { + if (currentSuper.hasHierarchyCheckStarted()) + break; + if (TypeBinding.equalsEquals(currentSuper, this) || TypeBinding.equalsEquals(currentSuper, tempSuper)) { + currentSuper.tagBits |= TagBits.HierarchyHasProblems; + if (currentSuper.isBinaryBinding()) + breakLoop(); + + return; + } + if (count == skipCount) { + tempSuper = currentSuper; // for finding loops that only start after a linear chain + skipCount *= 2; + count = 0; + } + //Ignore if the super is not yet resolved.. + if (!currentSuper.isHierarchyConnected()) + return; + currentSuper = currentSuper.superclass(); + count++; + } + /* No loop detected and completely found that there is no loop + * So, set that info for all the classes + */ + tempSuper = this; + while (TypeBinding.notEquals(currentSuper, tempSuper)) { + tempSuper.setHierarchyCheckDone(); + tempSuper=tempSuper.superclass(); + } +} + // NOTE: superInterfaces of binary types are resolved when needed @Override public ReferenceBinding[] superInterfaces() { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java index 537d99fbc3..98a822baae 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java @@ -275,6 +275,15 @@ public MethodBinding[] availableMethods() { return methods(); } +public boolean hasHierarchyCheckStarted() { + return (this.tagBits & TagBits.BeginHierarchyCheck) != 0; +} + +public void setHierarchyCheckDone() { + return; +} + + /** * Answer true if the receiver can be instantiated */ |