Skip to content

Commit

Permalink
NullPointerException during Java Search
Browse files Browse the repository at this point in the history
Resolve all type arguments even when the main type has an error

Fixes eclipse-jdt#3451
  • Loading branch information
stephan-herrmann committed Dec 19, 2024
1 parent 07c7cda commit 3f0602d
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -215,20 +215,7 @@ private TypeBinding internalResolveLeafType(Scope scope, boolean checkBounds) {
this.resolvedType = (ReferenceBinding) binding;
reportInvalidType(scope);
// be resilient, still attempt resolving arguments
for (int i = 0, max = this.tokens.length; i < max; i++) {
TypeReference[] args = this.typeArguments[i];
if (args != null) {
int argLength = args.length;
for (int j = 0; j < argLength; j++) {
TypeReference typeArgument = args[j];
if (isClassScope) {
typeArgument.resolveType((ClassScope) scope);
} else {
typeArgument.resolveType((BlockScope) scope, checkBounds);
}
}
}
}
resolveAllTypeArguments(0, scope, checkBounds, isClassScope);
return null;
}

Expand All @@ -244,20 +231,7 @@ private TypeBinding internalResolveLeafType(Scope scope, boolean checkBounds) {
if (!(this.resolvedType.isValidBinding())) {
reportInvalidType(scope);
// be resilient, still attempt resolving arguments
for (int j = i; j < max; j++) {
TypeReference[] args = this.typeArguments[j];
if (args != null) {
int argLength = args.length;
for (int k = 0; k < argLength; k++) {
TypeReference typeArgument = args[k];
if (isClassScope) {
typeArgument.resolveType((ClassScope) scope);
} else {
typeArgument.resolveType((BlockScope) scope);
}
}
}
}
resolveAllTypeArguments(0, scope, checkBounds, isClassScope);
return null;
}
ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
Expand Down Expand Up @@ -310,17 +284,21 @@ private TypeBinding internalResolveLeafType(Scope scope, boolean checkBounds) {
}
if (isClassScope) {
((ClassScope) scope).superTypeReference = keep;
if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this))
if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this)) {
resolveAllTypeArguments(i+1, scope, checkBounds, isClassScope);
return null;
}
}

TypeVariableBinding[] typeVariables = currentOriginal.typeVariables();
if (typeVariables == Binding.NO_TYPE_VARIABLES) { // check generic
scope.problemReporter().nonGenericTypeCannotBeParameterized(i, this, currentType, argTypes);
resolveAllTypeArguments(i+1, scope, checkBounds, isClassScope);
return null;
} else if (argLength != typeVariables.length) {
if (!isDiamond) { // check arity
scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes, i);
resolveAllTypeArguments(i+1, scope, checkBounds, isClassScope);
return null;
}
}
Expand Down Expand Up @@ -352,8 +330,10 @@ private TypeBinding internalResolveLeafType(Scope scope, boolean checkBounds) {
} else {
ReferenceBinding currentOriginal = (ReferenceBinding)currentType.original();
if (isClassScope)
if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this))
if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this)) {
resolveAllTypeArguments(0, scope, checkBounds, isClassScope);
return null;
}
if (currentOriginal.isGenericType()) {
if (typeIsConsistent && qualifyingType != null && qualifyingType.isParameterizedType() && currentOriginal.hasEnclosingInstanceContext()) {
scope.problemReporter().parameterizedMemberTypeMissingArguments(this, scope.environment().createParameterizedType(currentOriginal, null, qualifyingType), i);
Expand All @@ -372,6 +352,22 @@ private TypeBinding internalResolveLeafType(Scope scope, boolean checkBounds) {
}
return this.resolvedType;
}
private void resolveAllTypeArguments(int from, Scope scope, boolean checkBounds, boolean isClassScope) {
for (int i = from, max = this.tokens.length; i < max; i++) {
TypeReference[] args = this.typeArguments[i];
if (args != null) {
int argLength = args.length;
for (int j = 0; j < argLength; j++) {
TypeReference typeArgument = args[j];
if (isClassScope) {
typeArgument.resolveType((ClassScope) scope);
} else {
typeArgument.resolveType((BlockScope) scope, checkBounds);
}
}
}
}
}
private void createArrayType(Scope scope) {
if (this.dimensions > 0) {
if (this.dimensions > 255)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35345,27 +35345,32 @@ public void test1036() {
" ^^^^^^\n" +
"The type String is not generic; it cannot be parameterized with arguments <Object>\n" +
"----------\n" +
"20. ERROR in X.java (at line 10)\n" +
"20. ERROR in X.java (at line 9)\n" +
" String<Object>.Y<List> y; // wrong\n" +
" ^^^^\n" +
"List cannot be resolved to a type\n" +
"----------\n" +
"21. ERROR in X.java (at line 10)\n" +
" X<Object>.Y<List> y1; // wrong\n" +
" ^^^^^^^^^^^\n" +
"X.Y cannot be resolved to a type\n" +
"----------\n" +
"21. ERROR in X.java (at line 10)\n" +
"22. ERROR in X.java (at line 10)\n" +
" X<Object>.Y<List> y1; // wrong\n" +
" ^^^^^^\n" +
"Bound mismatch: The type Object is not a valid substitute for the bounded parameter <T extends String> of the type X<T>\n" +
"----------\n" +
"22. ERROR in X.java (at line 10)\n" +
"23. ERROR in X.java (at line 10)\n" +
" X<Object>.Y<List> y1; // wrong\n" +
" ^^^^\n" +
"List cannot be resolved to a type\n" +
"----------\n" +
"23. ERROR in X.java (at line 11)\n" +
"24. ERROR in X.java (at line 11)\n" +
" X<String>.Y<List> y2;\n" +
" ^^^^^^^^^^^\n" +
"X.Y cannot be resolved to a type\n" +
"----------\n" +
"24. ERROR in X.java (at line 11)\n" +
"25. ERROR in X.java (at line 11)\n" +
" X<String>.Y<List> y2;\n" +
" ^^^^\n" +
"List cannot be resolved to a type\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10859,6 +10859,16 @@ public class TestClass implements TestClass.Missing1<TestClass.Missing2<TestClas
^^^^^^^^^^^^^^^^^^
Cycle detected: the type TestClass cannot extend/implement itself or one of its own member types
----------
2. ERROR in TestClass.java (at line 1)
public class TestClass implements TestClass.Missing1<TestClass.Missing2<TestClass.Missing3>> {
^^^^^^^^^^^^^^^^^^
TestClass.Missing2 cannot be resolved to a type
----------
3. ERROR in TestClass.java (at line 1)
public class TestClass implements TestClass.Missing1<TestClass.Missing2<TestClass.Missing3>> {
^^^^^^^^^^^^^^^^^^
TestClass.Missing3 cannot be resolved to a type
----------
""";
runner.runNegativeTest();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10430,4 +10430,64 @@ Implicit super constructor Object() is undefined for default constructor. Must d
}
runner.runNegativeTest();
}
public void testGH3451() {
Runner runner = new Runner();
String[] libs = getDefaultClassPaths();
int len = libs.length;
System.arraycopy(libs, 0, libs = new String[len+1], 0, len);
// contained gh3451/Abstract.class refers to missing super class gh3451.Super
libs[len] = this.getCompilerTestsPluginDirectoryPath() + File.separator + "workspace" + File.separator + "gh3451.jar";
runner.classLibraries = libs;
runner.testFiles = new String[] {
"test/Bug.java",
"""
package test;
import gh3451.Abstract;
public class Bug {
class Impl1 extends Abstract<@Annot String> {}
class Impl2 extends Abstract.Nested<@Annot Number> {}
Abstract<?> a1 = new Impl1();
Abstract<?> a2 = new Impl2();
}
"""
};
runner.expectedCompilerLog =
"""
----------
1. ERROR in test\\Bug.java (at line 6)
class Impl1 extends Abstract<@Annot String> {}
^^^^^
The hierarchy of the type Impl1 is inconsistent
----------
2. ERROR in test\\Bug.java (at line 6)
class Impl1 extends Abstract<@Annot String> {}
^^^^^^^^
The type gh3451.Super cannot be resolved. It is indirectly referenced from required type gh3451.Abstract
----------
3. ERROR in test\\Bug.java (at line 6)
class Impl1 extends Abstract<@Annot String> {}
^^^^^
Annot cannot be resolved to a type
----------
4. ERROR in test\\Bug.java (at line 7)
class Impl2 extends Abstract.Nested<@Annot Number> {}
^^^^^
The hierarchy of the type Impl2 is inconsistent
----------
5. ERROR in test\\Bug.java (at line 7)
class Impl2 extends Abstract.Nested<@Annot Number> {}
^^^^^
Annot cannot be resolved to a type
----------
6. ERROR in test\\Bug.java (at line 10)
Abstract<?> a2 = new Impl2();
^^^^^^^^^^^
Type mismatch: cannot convert from Bug.Impl2 to Abstract<?>
----------
""";
runner.runNegativeTest();
}
}
Binary file not shown.

0 comments on commit 3f0602d

Please sign in to comment.