Skip to content

Commit

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

Fixes #3451
  • Loading branch information
stephan-herrmann authored Dec 19, 2024
1 parent 07c7cda commit 6454567
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 6454567

Please sign in to comment.