diff options
3 files changed, 101 insertions, 15 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java index 807c5acd76..fa7f9233ec 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 328281 - visibility leaks not detected when analyzing unused field in private class + * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for + * bug 328281 - visibility leaks not detected when analyzing unused field in private class + * bug 379784 - [compiler] "Method can be static" is not getting reported *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; @@ -31,7 +33,7 @@ public ProblemTypeAndMethodTest(String name) { // Static initializer to specify tests subset using TESTS_* static variables // All specified tests which does not belong to the class are skipped... static { -// TESTS_NAMES = new String[] { "testBug335845g" }; +// TESTS_NAMES = new String[] { "test376550" }; // TESTS_NUMBERS = new int[] { 113 }; // TESTS_RANGE = new int[] { 108, -1 }; } @@ -7495,8 +7497,47 @@ public void test376550_5a() { ); } -//https://bugs.eclipse.org/bugs/show_bug.cgi?id=376550 -//QualifiedNameReference, accessing outer class instance field +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=376550 +// https://bugs.eclispe.org/379784 - [compiler] "Method can be static" is not getting reported +// Variation of the above +public void test376550_5aa() { + if (this.complianceLevel < ClassFileConstants.JDK1_5) + return; + Map compilerOptions = getCompilerOptions(); + compilerOptions.put(CompilerOptions.OPTION_ReportMethodCanBeStatic, CompilerOptions.ERROR); + compilerOptions.put(CompilerOptions.OPTION_ReportMethodCanBePotentiallyStatic, CompilerOptions.ERROR); + compilerOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.IGNORE); + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " int i1 = 1;\n" + + " public void foo(){\n" + + " class Local{\n" + + " int i2 = 1;\n" + + " }\n" + + " class Local2 extends Local {\n" + + " void method2() {\n" + + " Local2.this.i2 = 1;\n" + // required instance is of type Local (super of Local2) + " }\n" + + " }\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 3)\n" + + " public void foo(){\n" + + " ^^^^^\n" + + "The method foo() from the type X can potentially be declared as static\n" + + "----------\n", + null /* no extra class libraries */, + true /* flush output directory */, + compilerOptions /* custom options */ + ); +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=376550 +// QualifiedNameReference, accessing outer class instance field public void test376550_5b() { if (this.complianceLevel < ClassFileConstants.JDK1_5) return; @@ -7911,6 +7952,47 @@ public void test376550_11() { ); } +// https://bugs.eclipse.org/376550 +// https://bugs.eclipse.org/379784 - [compiler] "Method can be static" is not getting reported +// bug test case +public void test376550_11a() { + if (this.complianceLevel < ClassFileConstants.JDK1_5) + return; + Map compilerOptions = getCompilerOptions(); + compilerOptions.put(CompilerOptions.OPTION_ReportMethodCanBeStatic, CompilerOptions.ERROR); + compilerOptions.put(CompilerOptions.OPTION_ReportMethodCanBePotentiallyStatic, CompilerOptions.ERROR); + compilerOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.IGNORE); + this.runNegativeTest( + new String[] { + "X.java", + "import java.util.ArrayList;\n" + + "import java.util.Collection;\n" + + "public class X {\n" + + " private Object o = new Object();\n" + + " public final Collection<Object> go() {\n" +// can be static + " return new ArrayList<Object>() {\n" + + " { add(null);}\n" + // required instance is of type ArrayList, not X + " };\n" + + " }\n" + + "}" + }, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " public final Collection<Object> go() {\n" + + " ^^^^\n" + + "The method go() from the type X can be declared as static\n" + + "----------\n" + + "2. WARNING in X.java (at line 6)\n" + + " return new ArrayList<Object>() {\n" + + " ^^^^^^^^^^^^^^^^^^^\n" + + "The serializable class does not declare a static final serialVersionUID field of type long\n" + + "----------\n", + null /* no extra class libraries */, + true /* flush output directory */, + compilerOptions /* custom options */ + ); +} + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=376550 public void test376550_12() { if (this.complianceLevel < ClassFileConstants.JDK1_5) diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java index fb84b3cad2..e0beaceb0f 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java @@ -16,6 +16,7 @@ * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' + * bug 379784 - [compiler] "Method can be static" is not getting reported *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -88,7 +89,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682 if (this.receiver.isThis()) { // accessing non-static method without an object - currentScope.resetDeclaringClassMethodStaticFlag(this.binding.declaringClass); + currentScope.resetDeclaringClassMethodStaticFlag(this.actualReceiverType); } } else if (this.receiver.isThis()) { if ((this.receiver.bits & ASTNode.IsImplicitThis) == 0) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java index 4df6fbce4b..ee6637529f 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java @@ -14,6 +14,7 @@ * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' + * bug 379784 - [compiler] "Method can be static" is not getting reported *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -981,14 +982,16 @@ public void resetEnclosingMethodStaticFlag() { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=376550 /** * This method is used to reset the CanBeStatic on all enclosing methods until the method - * belonging to the declaringClass - * @param declaringClass + * belonging to the enclosingInstanceType + * @param enclosingInstanceType type of which an enclosing instance is required in the code. */ -public void resetDeclaringClassMethodStaticFlag(TypeBinding declaringClass) { +public void resetDeclaringClassMethodStaticFlag(TypeBinding enclosingInstanceType) { MethodScope methodScope = methodScope(); if (methodScope != null && methodScope.referenceContext instanceof TypeDeclaration) { - // anonymous type, find enclosing method - methodScope = methodScope.enclosingMethodScope(); + if (!methodScope.enclosingReceiverType().isCompatibleWith(enclosingInstanceType)) { // unless invoking a method of the local type ... + // anonymous type, find enclosing method + methodScope = methodScope.enclosingMethodScope(); + } } while (methodScope != null && methodScope.referenceContext instanceof MethodDeclaration) { MethodDeclaration methodDeclaration = (MethodDeclaration) methodScope.referenceContext; @@ -996,14 +999,14 @@ public void resetDeclaringClassMethodStaticFlag(TypeBinding declaringClass) { ClassScope enclosingClassScope = methodScope.enclosingClassScope(); if (enclosingClassScope != null) { TypeDeclaration type = enclosingClassScope.referenceContext; - if (type != null && type.binding != null && declaringClass != null && type.binding != declaringClass.original()) { + if (type != null && type.binding != null && enclosingInstanceType != null + && !type.binding.isCompatibleWith(enclosingInstanceType.original())) + { methodScope = enclosingClassScope.enclosingMethodScope(); - } else { - break; + continue; } - } else { - break; } + break; } } |