Skip to content

Commit

Permalink
Field "cannot be resolved or is not a field" when referenced from par…
Browse files Browse the repository at this point in the history
…ent class within annotation (eclipse-jdt#1447)

fixes eclipse-jdt#1431

More systematic approach to organize steps of LookupEnvironment.completeTypeBindings().

Also resolved some resource warnings introduced by PR 1446.
  • Loading branch information
stephan-herrmann authored Oct 15, 2023
1 parent eddafe9 commit 4647943
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
import org.eclipse.jdt.internal.compiler.problem.AbortType;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.compiler.problem.ShouldNotImplement;
import org.eclipse.jdt.internal.compiler.util.Messages;
Expand Down Expand Up @@ -2277,9 +2278,10 @@ public void completeCodeAttributeForSyntheticMethod(
if (exceptionLabel != null) {
int iRange = 0, maxRange = exceptionLabel.getCount();
if ((maxRange & 1) != 0) {
this.referenceBinding.scope.problemReporter().abortDueToInternalError(
ProblemReporter problemReporter = this.referenceBinding.scope.problemReporter();
problemReporter.abortDueToInternalError(
Messages.bind(Messages.abort_invalidExceptionAttribute, new String(binding.selector),
this.referenceBinding.scope.problemReporter().referenceContext));
problemReporter.referenceContext));
}
while (iRange < maxRange) {
int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1055,14 +1055,14 @@ private void verifyTypeReference(Expression reference, Expression typeReference,
int scopeModifiers = -1;

// reference must have enough visibility to be used
if (!canBeSeen(scope.problemReporter().options.reportInvalidJavadocTagsVisibility, modifiers)) {
if (!canBeSeen(scope.compilerOptions().reportInvalidJavadocTagsVisibility, modifiers)) {
scope.problemReporter().javadocHiddenReference(typeReference.sourceStart, reference.sourceEnd, scope, modifiers);
return;
}

// type reference must have enough visibility to be used
if (reference != typeReference) {
if (!canBeSeen(scope.problemReporter().options.reportInvalidJavadocTagsVisibility, resolvedType.modifiers)) {
if (!canBeSeen(scope.compilerOptions().reportInvalidJavadocTagsVisibility, resolvedType.modifiers)) {
scope.problemReporter().javadocHiddenReference(typeReference.sourceStart, typeReference.sourceEnd, scope, resolvedType.modifiers);
return;
}
Expand Down Expand Up @@ -1206,7 +1206,7 @@ private boolean verifyModuleReference(Expression reference, Expression typeRefer
}

if (!bindingFound) {
if (!canBeSeen(scope.problemReporter().options.reportInvalidJavadocTagsVisibility, moduleType.modifiers)) {
if (!canBeSeen(scope.compilerOptions().reportInvalidJavadocTagsVisibility, moduleType.modifiers)) {
scope.problemReporter().javadocHiddenReference(typeReference.sourceStart, typeReference.sourceEnd, scope, moduleType.modifiers);
return bindingFound;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,11 +391,11 @@ public char[] computeConstantPoolName(LocalTypeBinding localType) {
return candidateName;
}

void connectTypeHierarchy1() {
void connectTypeHierarchy() {
for (int i = 0, length = this.topLevelTypes.length; i < length; i++)
this.topLevelTypes[i].scope.connectTypeHierarchy();
}
void connectTypeHierarchy2() {
void integrateAnnotationsInHierarchy() {
// Only now that all hierarchy information is built we're ready for ...
// ... integrating annotations
for (int i = 0, length = this.topLevelTypes.length; i < length; i++)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,7 @@ public class LookupEnvironment implements ProblemReasons, TypeConstants {
public ProblemReporter problemReporter; // SHARED
public ClassFilePool classFilePool; // SHARED
// indicate in which step on the compilation we are.
// step 1 : build the reference binding
// step 2 : conect the hierarchy (connect bindings)
// step 3 : build fields and method bindings.
private int stepCompleted; // ROOT_ONLY
private CompleteTypeBindingsSteps stepCompleted = CompleteTypeBindingsSteps.NONE; // ROOT_ONLY
public ITypeRequestor typeRequestor; // SHARED

private SimpleLookupTable uniqueParameterizedGenericMethodBindings;
Expand Down Expand Up @@ -148,11 +145,37 @@ public class LookupEnvironment implements ProblemReasons, TypeConstants {

public String moduleVersion; // ROOT_ONLY

final static int BUILD_TYPE_HIERARCHY = 1;
final static int CHECK_AND_SET_IMPORTS = 2;
final static int CONNECT_TYPE_HIERARCHY1 = 3;
final static int BUILD_FIELDS_AND_METHODS = 4;
final static int CONNECT_TYPE_HIERARCHY2 = 5;
static enum CompleteTypeBindingsSteps {
NONE,
CHECK_AND_SET_IMPORTS,
CONNECT_TYPE_HIERARCHY,
BUILD_FIELDS_AND_METHODS,
INTEGRATE_ANNOTATIONS_IN_HIERARCHY,
CHECK_PARAMETERIZED_TYPES;

/** Answer the next step in sequence or {@code this} when we are at the last step already. */
CompleteTypeBindingsSteps next() {
CompleteTypeBindingsSteps[] values = values();
int nextOrdinal = ordinal() + 1;
if (nextOrdinal < values.length)
return values[nextOrdinal];
return this; // no-change to signal "at end"
}

/** values without NONE */
static final CompleteTypeBindingsSteps[] realValues = Arrays.copyOfRange(values(), 1, values().length-1);

void perform(CompilationUnitScope scope) {
switch (this) {
case CHECK_AND_SET_IMPORTS -> scope.checkAndSetImports();
case CONNECT_TYPE_HIERARCHY -> scope.connectTypeHierarchy();
case BUILD_FIELDS_AND_METHODS -> scope.buildFieldsAndMethods();
case INTEGRATE_ANNOTATIONS_IN_HIERARCHY -> scope.integrateAnnotationsInHierarchy();
case CHECK_PARAMETERIZED_TYPES -> scope.checkParameterizedTypes();
default -> throw new IllegalArgumentException("No implementation for: " + this); //$NON-NLS-1$
}
}
}

static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound, null/*not perfect*/);
static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR_CHAR, null, NotFound);
Expand Down Expand Up @@ -511,29 +534,18 @@ public void completeTypeBindings() {
this.root.completeTypeBindings();
return;
}
this.stepCompleted = BUILD_TYPE_HIERARCHY;

for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
(this.unitBeingCompleted = this.units[i]).scope.checkAndSetImports();
}
this.stepCompleted = CHECK_AND_SET_IMPORTS;

for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
(this.unitBeingCompleted = this.units[i]).scope.connectTypeHierarchy1();
}
this.stepCompleted = CONNECT_TYPE_HIERARCHY1;
for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
(this.unitBeingCompleted = this.units[i]).scope.connectTypeHierarchy2();
}
this.stepCompleted = CONNECT_TYPE_HIERARCHY2;

for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
CompilationUnitScope unitScope = (this.unitBeingCompleted = this.units[i]).scope;
unitScope.checkParameterizedTypes();
unitScope.buildFieldsAndMethods();
this.units[i] = null; // release unnecessary reference to the parsed unit
this.stepCompleted = CompleteTypeBindingsSteps.NONE;
for (CompleteTypeBindingsSteps step : CompleteTypeBindingsSteps.values()) {
CompleteTypeBindingsSteps next = step.next();
for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
if (next != step)
next.perform((this.unitBeingCompleted = this.units[i]).scope);
else
this.units[i] = null; // at last step clean up
}
this.stepCompleted = next;
}
this.stepCompleted = BUILD_FIELDS_AND_METHODS;
this.lastCompletedUnitIndex = this.lastUnitIndex;
this.unitBeingCompleted = null;
}
Expand All @@ -555,23 +567,18 @@ public void completeTypeBindings(CompilationUnitDeclaration parsedUnit) {
this.root.completeTypeBindings(parsedUnit);
return;
}
if (this.stepCompleted == BUILD_FIELDS_AND_METHODS) {
if (this.stepCompleted == this.stepCompleted.next()) {
// This can only happen because the original set of units are completely built and
// are now being processed, so we want to treat all the additional units as a group
// until they too are completely processed.
completeTypeBindings();
} else {
if (parsedUnit.scope == null) return; // parsing errors were too severe

if (this.stepCompleted >= CHECK_AND_SET_IMPORTS)
(this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports();

if (this.stepCompleted >= CONNECT_TYPE_HIERARCHY1)
(this.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy1();

if (this.stepCompleted >= CONNECT_TYPE_HIERARCHY2)
(this.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy2();

for (CompleteTypeBindingsSteps step : CompleteTypeBindingsSteps.realValues) {
if (this.stepCompleted.compareTo(step) >= 0)
step.perform((this.unitBeingCompleted = parsedUnit).scope);
}
this.unitBeingCompleted = null;
}
}
Expand All @@ -593,12 +600,11 @@ public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean
if (parsedUnit.scope == null) return; // parsing errors were too severe
LookupEnvironment rootEnv = this.root;
CompilationUnitDeclaration previousUnitBeingCompleted = rootEnv.unitBeingCompleted;
(rootEnv.unitBeingCompleted = parsedUnit).scope.checkAndSetImports();
parsedUnit.scope.connectTypeHierarchy1();
parsedUnit.scope.connectTypeHierarchy2();
parsedUnit.scope.checkParameterizedTypes();
if (buildFieldsAndMethods)
parsedUnit.scope.buildFieldsAndMethods();
for (CompleteTypeBindingsSteps step : CompleteTypeBindingsSteps.realValues) {
if (step != CompleteTypeBindingsSteps.BUILD_FIELDS_AND_METHODS || buildFieldsAndMethods)
step.perform((rootEnv.unitBeingCompleted = parsedUnit).scope);
}

rootEnv.unitBeingCompleted = previousUnitBeingCompleted;
}

Expand All @@ -612,29 +618,13 @@ public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean
*/
public void completeTypeBindings(CompilationUnitDeclaration[] parsedUnits, boolean[] buildFieldsAndMethods, int unitCount) {
LookupEnvironment rootEnv = this.root;
for (int i = 0; i < unitCount; i++) {
CompilationUnitDeclaration parsedUnit = parsedUnits[i];
if (parsedUnit.scope != null)
(rootEnv.unitBeingCompleted = parsedUnit).scope.checkAndSetImports();
}

for (int i = 0; i < unitCount; i++) {
CompilationUnitDeclaration parsedUnit = parsedUnits[i];
if (parsedUnit.scope != null)
(rootEnv.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy1();
}
for (int i = 0; i < unitCount; i++) {
CompilationUnitDeclaration parsedUnit = parsedUnits[i];
if (parsedUnit.scope != null)
(rootEnv.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy2();
}

for (int i = 0; i < unitCount; i++) {
CompilationUnitDeclaration parsedUnit = parsedUnits[i];
if (parsedUnit.scope != null) {
(rootEnv.unitBeingCompleted = parsedUnit).scope.checkParameterizedTypes();
if (buildFieldsAndMethods[i])
parsedUnit.scope.buildFieldsAndMethods();
for (CompleteTypeBindingsSteps step : CompleteTypeBindingsSteps.realValues) {
for (int i = 0; i < unitCount; i++) {
CompilationUnitDeclaration parsedUnit = parsedUnits[i];
if (parsedUnit.scope != null)
if (step != CompleteTypeBindingsSteps.BUILD_FIELDS_AND_METHODS || buildFieldsAndMethods[i]) {
step.perform((rootEnv.unitBeingCompleted = parsedUnit).scope);
}
}
}

Expand Down Expand Up @@ -2180,7 +2170,7 @@ public void reset() {
this.root.reset();
return;
}
this.stepCompleted = 0;
this.stepCompleted = CompleteTypeBindingsSteps.NONE;
this.knownModules = new HashtableOfModule();
this.UnNamedModule = new ModuleBinding.UnNamedModule(this);
this.module = this.UnNamedModule;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,14 @@ public void diagnoseParse(boolean record) {
this.deferredErrorStart = this.deferredErrorEnd = -1;
diagnoseParse0(record);
} finally {
ReferenceContext referenceContext = this.problemReporter().referenceContext;
CompilationResult compilationResult = referenceContext != null ? referenceContext.compilationResult() : null;
if (compilationResult != null && !compilationResult.hasSyntaxError) {
reportMisplacedConstruct(this.deferredErrorStart, this.deferredErrorEnd, true);
try (ProblemReporter problemReporter = this.problemReporter()) {
ReferenceContext referenceContext = problemReporter.referenceContext;
CompilationResult compilationResult = referenceContext != null ? referenceContext.compilationResult() : null;
if (compilationResult != null && !compilationResult.hasSyntaxError) {
reportMisplacedConstruct(this.deferredErrorStart, this.deferredErrorEnd, true);
}
this.deferredErrorStart = this.deferredErrorEnd = -1;
}
this.deferredErrorStart = this.deferredErrorEnd = -1;
}
}

Expand Down Expand Up @@ -404,9 +406,11 @@ private void diagnoseParse0(boolean record) {
return;
}

if(this.parser.problemReporter().options.maxProblemsPerUnit < this.parser.compilationUnit.compilationResult.problemCount) {
if(this.recoveryScanner == null || !this.recoveryScanner.record) return;
this.reportProblem = false;
try (ProblemReporter problemReporter = this.parser.problemReporter()) {
if(problemReporter.options.maxProblemsPerUnit < this.parser.compilationUnit.compilationResult.problemCount) {
if(this.recoveryScanner == null || !this.recoveryScanner.record) return;
this.reportProblem = false;
}
}

act = this.stack[this.stateStackTop];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,31 @@ public void testBug542795() throws Exception {
"----------\n";
runner.runNegativeTest();
}
public void testGH1431() {
Runner runner = new Runner();
runner.testFiles = new String[] {
"Parent.java",
"""
@Deprecated(since = AbstractChild.TEST_CONSTANT) // this now fails
public class Parent extends AbstractChild {
private static final String REF_OK = AbstractChild.TEST_CONSTANT; // this compiles OK
}
""",
"AbstractChild.java",
"""
public abstract class AbstractChild implements Constants {
// redacted for brevity
}
""",
"Constants.java",
"""
public interface Constants {
public static final String TEST_CONSTANT = "this is a test";
}
"""
};
runner.runConformTest();
}
public void testGH1412() {
Runner runner = new Runner();
runner.testFiles = new String[] {
Expand Down

0 comments on commit 4647943

Please sign in to comment.