Skip to content

Commit

Permalink
Fix deprecated check routines in ASTNode to also check since value (#…
Browse files Browse the repository at this point in the history
…2874)

Fix deprecated check routines in ASTNode to also check since value
* Tweak logic to handle case where annotations aren't ready

fixes #2873
  • Loading branch information
jjohnstn authored Oct 26, 2024
1 parent bad4880 commit 41b0c39
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationPosition;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.StringConstant;
import org.eclipse.jdt.internal.compiler.lookup.*;

@SuppressWarnings({"rawtypes", "unchecked"})
Expand Down Expand Up @@ -498,6 +500,8 @@ public final boolean isFieldUseDeprecated(FieldBinding field, Scope scope, int f
// inside same unit - no report
if (scope.isDefinedInSameUnit(field.declaringClass)) return false;

if (sinceValueUnreached(field, scope)) return false;

// if context is deprecated, may avoid reporting
if (!scope.compilerOptions().reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false;
return true;
Expand Down Expand Up @@ -548,6 +552,8 @@ public final boolean isMethodUseDeprecated(MethodBinding method, Scope scope,
// inside same unit - no report
if (scope.isDefinedInSameUnit(method.declaringClass)) return false;

if (sinceValueUnreached(method, scope)) return false;

// non explicit use and non explicitly deprecated - no report
if (!isExplicitUse &&
(method.modifiers & ClassFileConstants.AccDeprecated) == 0) {
Expand All @@ -559,6 +565,37 @@ public final boolean isMethodUseDeprecated(MethodBinding method, Scope scope,
return true;
}

private boolean sinceValueUnreached(Binding binding, Scope scope) {
if (binding instanceof TypeBinding typeBinding) {
if (!typeBinding.isReadyForAnnotations()) {
return false;
}
}
AnnotationBinding[] annotations = binding.getAnnotations();
for (AnnotationBinding annotation : annotations) {
if (annotation != null && annotation.getAnnotationType().id == TypeIds.T_JavaLangDeprecated) {
ElementValuePair[] pairs = annotation.getElementValuePairs();
for (ElementValuePair pair : pairs) {
if (CharOperation.equals(pair.getName(), TypeConstants.SINCE)) {
if (pair.getValue() instanceof StringConstant strConstant) {
try {
String value = strConstant.stringValue();
long sinceLevel = CompilerOptions.versionToJdkLevel(value);
long complianceLevel = scope.compilerOptions().complianceLevel;
if (complianceLevel < sinceLevel) {
return true;
}
} catch (NumberFormatException e) {
// do nothing and fall through
}
}
}
}
}
}
return false;
}

public boolean isSuper() {

return false;
Expand Down Expand Up @@ -619,6 +656,8 @@ public final boolean isTypeUseDeprecated(TypeBinding type, Scope scope) {
// inside same unit - no report
if (scope.isDefinedInSameUnit(refType)) return false;

if (sinceValueUnreached(refType, scope)) return false;

// if context is deprecated, may avoid reporting
if (!scope.compilerOptions().reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false;
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import junit.framework.Test;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.compiler.batch.FileSystem;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;

Expand Down Expand Up @@ -913,7 +914,10 @@ public void testBug533063_2() throws Exception {
"----------\n";
runner.runWarningTest();
}
public void testBug534304() throws Exception {
public void testBug534304_1() throws Exception {
if (this.complianceLevel < ClassFileConstants.JDK13) {
return;
}
runNegativeTest(
new String[] {
"p1/C1.java",
Expand Down Expand Up @@ -953,6 +957,43 @@ public void testBug534304() throws Exception {
"CMissing cannot be resolved to a type\n" +
"----------\n");
}
public void testBug534304_2() throws Exception {
if (this.complianceLevel < ClassFileConstants.JDK13) {
runNegativeTest(
new String[] {
"p1/C1.java",
"package p1;\n" +
"\n" +
"import pdep.Dep1;\n" +
"\n" +
"public class C1 {\n" +
" Dep1 f;\n" +
"}\n",
"pdep/Dep1.java",
"package pdep;\n" +
"\n" +
"import pmissing.CMissing;\n" +
"\n" +
"@Deprecated(since=\"13\")\n" +
"@CMissing\n" +
"public class Dep1 {\n" +
"\n" +
"}\n"
},
"----------\n" +
"----------\n" +
"1. ERROR in pdep\\Dep1.java (at line 3)\n" +
" import pmissing.CMissing;\n" +
" ^^^^^^^^\n" +
"The import pmissing cannot be resolved\n" +
"----------\n" +
"2. ERROR in pdep\\Dep1.java (at line 6)\n" +
" @CMissing\n" +
" ^^^^^^^^\n" +
"CMissing cannot be resolved to a type\n" +
"----------\n");
}
}
public void testBug542795() throws Exception {
Runner runner = new Runner();
runner.customOptions = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2021 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 @@ -402,6 +402,65 @@ public void testTerminalDeprecation2() throws CoreException, IOException {
deleteProject("P1");
}
}
public void testSinceDeprecation() throws CoreException, IOException {
try {
IJavaProject p1 = createJava9Project("P1");
String x1Source = "package p;\n" +
"public class X1 {\n" +
"@Deprecated(since=\"10\")\n" +
"public void foo() {}\n" +
"}";
String x2Source = "package p;\n" +
"public class X2 {\n" +
" public Object field;\n" +
" @Deprecated(since=\"9\")\n" +
" public void m() {}\n" +
"}\n";
String[] allJarSources = (isJRE9)
? new String[] {
"p/X1.java",
x1Source,
"/P1/src/p/X2.java",
x2Source }
: new String[] {
"java/lang/Deprecated.java",
"package java.lang;\n" +
"public @interface Deprecated {\n" +
" String since default \"\";" +
" boolean forRemoval() default false;" +
"}\n",
"p/X1.java",
x1Source,
"/P1/src/p/X2.java",
x2Source };
createJar(
allJarSources,
p1.getProject().getLocation().append("lib.jar").toOSString(),
null,
"9");
p1.getProject().refreshLocal(2, null);
addLibraryEntry(p1, "/P1/lib.jar", false);

setUpWorkingCopy("/P1/src/Y.java",
"public class Y {\n" +
" Object foo(p.X1 x1, p.X2 x2) {\n" +
" x2.m();\n" +
" x1.foo();\n" +
" return x2.field;\n" +
" }\n" +
"}\n");
assertProblems(
"Unexpected problems",
"----------\n" +
"1. WARNING in /P1/src/Y.java (at line 3)\n" +
" x2.m();\n" +
" ^^^\n" +
"The method m() from the type X2 is deprecated since version 9\n" +
"----------\n");
} finally {
deleteProject("P1");
}
}
public void testBug540541() throws CoreException, IOException {
if (!isJRE9) return;
IJavaProject project1 = null;
Expand Down

0 comments on commit 41b0c39

Please sign in to comment.