Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2011-10-25 16:30:31 +0000
committerStephan Herrmann2011-10-25 16:30:31 +0000
commit6dcbb38068eee59acb310076b78bc9a8183f88b8 (patch)
tree5970dc8f2ddd2fddbec81152e18faccb2710d493 /org.eclipse.jdt.core
parent608b50502644f795c100c2571772d0519a266d4a (diff)
downloadorg.eclipse.objectteams-6dcbb38068eee59acb310076b78bc9a8183f88b8.tar.gz
org.eclipse.objectteams-6dcbb38068eee59acb310076b78bc9a8183f88b8.tar.xz
org.eclipse.objectteams-6dcbb38068eee59acb310076b78bc9a8183f88b8.zip
update sources to v_C18, build config to v_C17 (no build containing C18 is available at this point)
Diffstat (limited to 'org.eclipse.jdt.core')
-rw-r--r--org.eclipse.jdt.core/.settings/org.eclipse.core.runtime.prefs2
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java100
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties26
-rw-r--r--org.eclipse.jdt.core/buildnotes_jdt-core.html393
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java19
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java11
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java20
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java237
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java17
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java18
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java19
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java11
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java21
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java36
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java13
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java15
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java44
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java47
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java37
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java40
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java41
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java174
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java1
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java17
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java84
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java33
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java19
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java22
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java20
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java84
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties14
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/RoleMigrationImplementor.java28
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TeamMethodGenerator.java4
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java4
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java2
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java22
-rw-r--r--org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java13
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java11
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java7
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java12
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java64
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java15
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java8
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBootstrapMethodsAttribute.java40
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBootstrapMethodsEntry.java24
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBytecodeVisitor.java10
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java14
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java71
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry.java57
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry2.java59
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java13
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java46
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathValidation.java14
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java7
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java11
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java1
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java13
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java25
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java7
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java1
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java4
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BootstrapMethodsAttribute.java63
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BootstrapMethodsEntry.java52
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java16
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java7
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java73
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry.java3
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry2.java66
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java29
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java151
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java16
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties17
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java2
101 files changed, 2591 insertions, 305 deletions
diff --git a/org.eclipse.jdt.core/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.jdt.core/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 000000000..5a0ad22d2
--- /dev/null
+++ b/org.eclipse.jdt.core/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index 47bf67c78..58ed763ed 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -10,8 +10,10 @@
* Tom Tromey - Contribution for bug 125961
* Tom Tromey - Contribution for bug 159641
* Benjamin Muskalla - Contribution for bug 239066
- * Stephan Herrmann - Contribution for bug 236385
- * Stephan Herrmann - Contribution for bug 295551
+ * Stephan Herrmann - Contributions for
+ * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
+ * bug 295551 - Add option to automatically promote all warnings to errors
+ * bug 359721 - [options] add command line option for new warning token "resource"
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -2243,7 +2245,7 @@ public void configure(String[] argv) {
this.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
}
if (currentArg.startsWith("-nowarn")) { //$NON-NLS-1$
- disableWarnings();
+ disableAll(ProblemSeverities.Warning);
mode = DEFAULT;
continue;
}
@@ -2252,7 +2254,7 @@ public void configure(String[] argv) {
String warningOption = currentArg;
int length = currentArg.length();
if (length == 10 && warningOption.equals("-warn:" + NONE)) { //$NON-NLS-1$
- disableWarnings();
+ disableAll(ProblemSeverities.Warning);
continue;
}
if (length <= 6) {
@@ -2260,23 +2262,20 @@ public void configure(String[] argv) {
this.bind("configure.invalidWarningConfiguration", warningOption)); //$NON-NLS-1$
}
int warnTokenStart;
- boolean isEnabling, allowPlusOrMinus;
+ boolean isEnabling;
switch (warningOption.charAt(6)) {
case '+' :
warnTokenStart = 7;
isEnabling = true;
- allowPlusOrMinus = true;
break;
case '-' :
warnTokenStart = 7;
isEnabling = false; // specified warnings are disabled
- allowPlusOrMinus = true;
break;
default:
- disableWarnings();
+ disableAll(ProblemSeverities.Warning);
warnTokenStart = 6;
isEnabling = true;
- allowPlusOrMinus = false;
}
StringTokenizer tokenizer =
@@ -2292,22 +2291,12 @@ public void configure(String[] argv) {
tokenCounter++;
switch(token.charAt(0)) {
case '+' :
- if (allowPlusOrMinus) {
- isEnabling = true;
- token = token.substring(1);
- } else {
- throw new IllegalArgumentException(
- this.bind("configure.invalidUsageOfPlusOption", token)); //$NON-NLS-1$
- }
+ isEnabling = true;
+ token = token.substring(1);
break;
case '-' :
- if (allowPlusOrMinus) {
- isEnabling = false;
- token = token.substring(1);
- } else {
- throw new IllegalArgumentException(
- this.bind("configure.invalidUsageOfMinusOption", token)); //$NON-NLS-1$
- }
+ isEnabling = false;
+ token = token.substring(1);
}
handleWarningToken(token, isEnabling);
}
@@ -2326,23 +2315,20 @@ public void configure(String[] argv) {
this.bind("configure.invalidErrorConfiguration", errorOption)); //$NON-NLS-1$
}
int errorTokenStart;
- boolean isEnabling, allowPlusOrMinus;
+ boolean isEnabling;
switch (errorOption.charAt(5)) {
case '+' :
errorTokenStart = 6;
isEnabling = true;
- allowPlusOrMinus = true;
break;
case '-' :
errorTokenStart = 6;
isEnabling = false; // specified errors are disabled
- allowPlusOrMinus = true;
break;
default:
- disableErrors();
+ disableAll(ProblemSeverities.Error);
errorTokenStart = 5;
isEnabling = true;
- allowPlusOrMinus = false;
}
StringTokenizer tokenizer =
@@ -2354,22 +2340,12 @@ public void configure(String[] argv) {
tokenCounter++;
switch(token.charAt(0)) {
case '+' :
- if (allowPlusOrMinus) {
- isEnabling = true;
- token = token.substring(1);
- } else {
- throw new IllegalArgumentException(
- this.bind("configure.invalidUsageOfPlusOption", token)); //$NON-NLS-1$
- }
+ isEnabling = true;
+ token = token.substring(1);
break;
case '-' :
- if (allowPlusOrMinus) {
- isEnabling = false;
- token = token.substring(1);
- } else {
- throw new IllegalArgumentException(
- this.bind("configure.invalidUsageOfMinusOption", token)); //$NON-NLS-1$
- }
+ isEnabling = false;
+ token = token.substring(1);
break;
}
handleErrorToken(token, isEnabling);
@@ -2901,7 +2877,16 @@ private void initializeWarnings(String propertiesFile) {
// SH}
}
}
-protected void disableWarnings() {
+protected void enableAll(int severity) {
+ String newValue = null;
+ switch(severity) {
+ case ProblemSeverities.Error :
+ newValue = CompilerOptions.ERROR;
+ break;
+ case ProblemSeverities.Warning :
+ newValue = CompilerOptions.WARNING;
+ break;
+ }
Object[] entries = this.options.entrySet().toArray();
for (int i = 0, max = entries.length; i < max; i++) {
Map.Entry entry = (Map.Entry) entries[i];
@@ -2909,13 +2894,22 @@ protected void disableWarnings() {
continue;
if (!(entry.getValue() instanceof String))
continue;
- if (((String) entry.getValue()).equals(CompilerOptions.WARNING)) {
- this.options.put(entry.getKey(), CompilerOptions.IGNORE);
+ if (((String) entry.getValue()).equals(CompilerOptions.IGNORE)) {
+ this.options.put(entry.getKey(), newValue);
}
}
this.options.put(CompilerOptions.OPTION_TaskTags, Util.EMPTY_STRING);
}
-protected void disableErrors() {
+protected void disableAll(int severity) {
+ String checkedValue = null;
+ switch(severity) {
+ case ProblemSeverities.Error :
+ checkedValue = CompilerOptions.ERROR;
+ break;
+ case ProblemSeverities.Warning :
+ checkedValue = CompilerOptions.WARNING;
+ break;
+ }
Object[] entries = this.options.entrySet().toArray();
for (int i = 0, max = entries.length; i < max; i++) {
Map.Entry entry = (Map.Entry) entries[i];
@@ -2923,7 +2917,7 @@ protected void disableErrors() {
continue;
if (!(entry.getValue() instanceof String))
continue;
- if (((String) entry.getValue()).equals(CompilerOptions.ERROR)) {
+ if (((String) entry.getValue()).equals(checkedValue)) {
this.options.put(entry.getKey(), CompilerOptions.IGNORE);
}
}
@@ -3334,6 +3328,13 @@ private void handleErrorOrWarningToken(String token, boolean isEnabling, int sev
setSeverity(CompilerOptions.OPTION_ReportMethodCanBeStatic, severity, isEnabling);
setSeverity(CompilerOptions.OPTION_ReportMethodCanBePotentiallyStatic, severity, isEnabling);
return;
+ } else if (token.equals("all")) { //$NON-NLS-1$
+ if (isEnabling) {
+ enableAll(severity);
+ } else {
+ disableAll(severity);
+ }
+ return;
//{ObjectTeams:
} else if (token.equals("ambiguousbinding")) { //$NON-NLS-1$
setSeverity(CompilerOptions.OPTION_ReportPotentialAmbiguousPlayedby, severity, isEnabling);
@@ -3578,6 +3579,11 @@ private void handleErrorOrWarningToken(String token, boolean isEnabling, int sev
} else if (/*token.equals("intfRedundant") ||*/ token.equals("redundantSuperinterface")) { //$NON-NLS-1$
setSeverity(CompilerOptions.OPTION_ReportRedundantSuperinterface, severity, isEnabling);
return;
+ } else if (token.equals("resource")) { //$NON-NLS-1$
+ setSeverity(CompilerOptions.OPTION_ReportUnclosedCloseable, severity, isEnabling);
+ setSeverity(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, severity, isEnabling);
+ setSeverity(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, severity, isEnabling);
+ return;
//{ObjectTeams:
} else if (token.equals("roleinstantiation")) { //$NON-NLS-1$
setSeverity(CompilerOptions.OPTION_ReportUnsafeRoleInstantiation, severity, isEnabling);
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
index ec64bbe12..8a658edfe 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -1,12 +1,30 @@
+###############################################################################
+# Copyright (c) 2000, 2011 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+# Benjamin Muskalla - Contribution for bug 239066
+# Stephan Herrmann - Contributions for
+# bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
+# bug 295551 - Add option to automatically promote all warnings to errors
+# bug 359721 - [options] add command line option for new warning token "resource"
+###############################################################################
+### JavaBatchCompiler messages.
+
+### compiler
#Format: compiler.name = word1 word2 word3
compiler.name = Eclipse Compiler for Java(TM)
#Format: compiler.version = 0.XXX[, other words (don't forget the comma if adding other words)]
-compiler.version = 0.C10, 3.8.0 M2
+compiler.version = 0.C18, 3.8.0 M3
compiler.copyright = Copyright IBM Corp 2000, 2011. All rights reserved.
###{ObjectTeams:
otdtc.name = Extension for Object Teams
-otdtc.version = 2.1.0 M2 $LastChangedRevision$ $LastChangedDate$
+otdtc.version = 2.1.0 M3 $LastChangedRevision$ $LastChangedDate$
otdtc.copyright = Copyright by TU Berlin, Fraunhofer FIRST and others, 2004, 2011.
### SH}
### progress
@@ -57,8 +75,6 @@ configure.maxProblems = max problems must be a positive integer: {0}
configure.invalidErrorConfiguration = invalid error configuration: ''{0}''
configure.invalidError = invalid error token: ''{0}''. Ignoring this error token and compiling
configure.invalidErrorOption = invalid error option: ''{0}''. Must specify an error token
-configure.invalidUsageOfPlusOption=usage of ''+'' for ''{0}'' is illegal there
-configure.invalidUsageOfMinusOption=usage of ''-'' for ''{0}'' is illegal there
## configure.directoryNotExist = directory does not exist: {0}
configure.unrecognizedOption = Unrecognized option : {0}
@@ -262,6 +278,7 @@ misc.usage.warn = {1} {2}\n\
\ -warn:-<warnings separated by ,> disable specific warnings\n\
\ abstractrelevantrole + abstract relevant role (OTJLD 2.5(b))\n\
\ adaptDeprecated + adapting a deprecated type/method\n\
+\ all enable all warnings\n\
\ allDeadCode dead code including trivial if(DEBUG) check\n\
\ allDeprecation deprecation including inside deprecated code\n\
\ allJavadoc invalid or missing javadoc\n\
@@ -323,6 +340,7 @@ misc.usage.warn = {1} {2}\n\
\ paramAssign assignment to a parameter\n\
\ pkgDefaultMethod + attempt to override package-default method\n\
\ raw + usage of raw type\n\
+\ resource + (pot.) unsafe usage of resource of type Closeable\n\
\ roleinstantiation + unsafe instantiation of a role\n\
\ (OTJLD 2.4.1(c), 2.4.3)\n\
\ roletypesyntax + old style syntax for role types (dependent types)\n\
diff --git a/org.eclipse.jdt.core/buildnotes_jdt-core.html b/org.eclipse.jdt.core/buildnotes_jdt-core.html
index f1baf89d6..9d3e66f4b 100644
--- a/org.eclipse.jdt.core/buildnotes_jdt-core.html
+++ b/org.eclipse.jdt.core/buildnotes_jdt-core.html
@@ -42,6 +42,393 @@
</td>
</tr>
</table>
+<a name="v_C18"></a>
+<hr><h1>
+Eclipse Platform Build Notes<br>
+Java development tools core</h1>
+Eclipse SDK 3.8.0 - October 25, 2011 - 3.8.0 M3
+<br>Project org.eclipse.jdt.core v_C18
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_C18">cvs</a>).
+<h2>What's new in this drop</h2>
+
+<h3>Problem Reports Fixed</h3>
+
+<a name="v_C17"></a>
+<hr><h1>
+Eclipse Platform Build Notes<br>
+Java development tools core</h1>
+Eclipse SDK 3.8.0 - October 20, 2011
+<br>Project org.eclipse.jdt.core v_C17
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_C17">cvs</a>).
+<h2>What's new in this drop</h2>
+<ul>
+<li>Added a new API OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE(see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=287164">287164</a> for details):
+<pre>
+/**
+ * Status constant indicating that the default or specific output folder is overlapping
+ * with another source location.
+ * @since 3.8
+ */
+public static final int OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE = 1013;
+</pre>
+</li>
+
+<li>Added a new option CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE to report an output location overlapping another source location(see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=287164">287164</a> for details):
+<pre>
+/**
+ * Core option ID: Reporting an output location overlapping another source location.
+ * Indicate the severity of the problem reported when a source entry's output location overlaps another
+ * source entry.
+ *
+ * Option id:"org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource"
+ * Possible values:{ "error", "warning", "ignore" }
+ * Default:"error"
+ *
+ * @since 3.8
+ */
+public static final String CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE = PLUGIN_ID + ".classpath.outputOverlappingAnotherSource";
+</pre>
+</li>
+</ul>
+<h3>Problem Reports Fixed</h3>
+<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=287164">287164</a>
+Report build path error if source folder has other source folder as output folder
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359721">359721</a>
+[options] add command line option for new warning token &quot;resource&quot;
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=343480">343480</a>
+[compiler] Incorrect/confusing error message on inner class static field declaration
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=318401">318401</a>
+FUP of 317858: Clarify eclipse compiler behavior on imports &amp; shadowing
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=360317">360317</a>
+[compiler] report switch over enum in 1.4- mode
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=360164">360164</a>
+Compile error in XSDImpl
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359727">359727</a>
+[1.7][doc] Update doc for new resource leak warnings
+
+<a name="v_C16"></a>
+<hr><h1>
+Eclipse Platform Build Notes<br>
+Java development tools core</h1>
+Eclipse SDK 3.8.0 - October 18, 2011
+<br>Project org.eclipse.jdt.core v_C16
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_C16">cvs</a>).
+<h2>What's new in this drop</h2>
+<ul>
+<li>Added a new API IBootstrapMethodsEntry to describe the bootstrap method table entry(see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359943">359943</a> for details):
+<pre>
+/**
+ * Description of a bootstrap method table entry as specified in the JVM specifications.
+ *
+ * This interface may be implemented by clients.
+ *
+ * @since 3.8
+ */
+public interface IBootstrapMethodsEntry;
+</pre>
+</li>
+
+<li>Added a new API IBootstrapMethodsAttribute to describe the bootstrap method attribute(see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359943">359943</a> for details):
+<pre>
+/**
+ * Description of a bootstrap methods attribute as described in the JVM specifications.
+ *
+ * This interface may be implemented by clients.
+ *
+ * @since 3.8
+ */
+public interface IBootstrapMethodsAttribute
+</pre>
+</li>
+
+<li>Added a new API in IBootstrapMethodsAttribute to obtain the number of bootstrap methods of this entry(see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359943">359943</a> for details):
+<pre>
+/**
+ * Answer back the number of bootstrap methods of this entry as specified in
+ * the JVM specifications.
+ *
+ * @return the number of bootstrap methods of this entry as specified in
+ * the JVM specifications
+ */
+int getBootstrapMethodsLength();
+</pre>
+</li>
+
+<li>Added a new API in IBootstrapMethodsAttribute to obtain the bootstrap methods table of this entry(see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359943">359943</a> for details):
+<pre>
+/**
+ * Answer back the bootstrap methods table of this entry as specified in
+ * the JVM specifications. Answer an empty array if none.
+ *
+ * @return the bootstrap methods table of this entry as specified in
+ * the JVM specifications. Answer an empty array if none
+ */
+IBootstrapMethodsEntry[] getBootstrapMethods();
+</pre>
+</li>
+
+<li>Added IConstantPoolEntry2 to describe the new constant pool entry from Java 7 onwards(see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359943">359943</a> for details):
+<pre>
+/**
+ * Description of the new constant pool entry as described in the JVM specifications
+ * added for Java 7 support.
+ * Its contents is initialized according to its kind.
+ *
+ * This interface may be implemented by clients.
+ *
+ * @since 3.8
+ */
+public interface IConstantPoolEntry2
+</pre>
+</li>
+
+<li>Added new API in IConstantPoolEntry2 to return the descriptor index for MethodType entry(see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359943">359943</a> for details):
+<pre>
+/**
+ * Returns the descriptor index. This value is set only when decoding a MethodType entry.
+ * The value is unspecified otherwise. The corresponding UTF8 value can be retrieved by using
+ * {@link #getMethodDescriptor()}.
+ *
+ * @return the descriptor index. This value is set only when decoding a MethodType entry.
+ * @see IConstantPoolConstant#CONSTANT_MethodType
+ */
+int getDescriptorIndex();
+</pre>
+</li>
+
+<li>Added new API in IConstantPoolEntry2 to return the reference kind for MethodHandle entry(see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359943">359943</a> for details):
+<pre>
+/**
+ * Returns the reference kind. This value is set only when decoding a MethodHandle entry.
+ * The value is unspecified otherwise.
+ *
+ * @return the reference kind. This value is set only when decoding a MethodHandle entry.
+ * @see IConstantPoolConstant#CONSTANT_MethodHandle
+ */
+int getReferenceKind();
+</pre>
+</li>
+
+<li>Added new API in IConstantPoolEntry2 to return the reference index for MethodHandle entry(see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359943">359943</a> for details):
+<pre>
+/**
+ * Returns the reference index. This value is set only when decoding a MethodHandle entry.
+ * The value is unspecified otherwise.
+ *
+ * @return the reference kind. This value is set only when decoding a MethodHandle entry.
+ * @see IConstantPoolConstant#CONSTANT_MethodHandle
+ */
+int getReferenceIndex();
+</pre>
+</li>
+
+<li>Added new API in IConstantPoolEntry2 to return the bootstrap method attribute index(see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359943">359943</a> for details):
+<pre>
+/**
+ * Returns the bootstrap method attribute index. This value is set only when decoding a InvokeDynamic entry.
+ * The value is unspecified otherwise.
+ *
+ * @return the reference kind. This value is set only when decoding a MethodHandle entry.
+ * @see IConstantPoolConstant#CONSTANT_InvokeDynamic
+ */
+int getBootstrapMethodAttributeIndex();
+</pre>
+</li>
+
+<li>Added new API in IByteCodeVisitor(see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359943">359943</a> for details):
+<pre>
+ /**
+ * @since 3.8
+ */
+ void _invokedynamic(
+ int pc,
+ int index,
+ IConstantPoolEntry invokeDynamic);
+</pre>
+<p>
+This has been added in place of the deprecated API
+<pre>
+ void _invokedynamic(
+ int pc,
+ int index,
+ IConstantPoolEntry nameEntry,
+ IConstantPoolEntry descriptorEntry);
+</pre>
+</li>
+</ul>
+<h3>Problem Reports Fixed</h3>
+<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359943">359943</a>
+invokedynamic in generated class file is not correctly recognized by the eclipse compiler
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=360644">360644</a>
+Scope.isDefinedInSameUnit(ReferenceBinding) fails for a ParameterizedTypeBinding
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=358762">358762</a>
+NPE in JDT compiler
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=360328">360328</a>
+[compiler][null] detect null problems in nested code (local class inside a loop)
+
+<a name="v_C15"></a>
+<hr><h1>
+Eclipse Platform Build Notes<br>
+Java development tools core</h1>
+Eclipse SDK 3.8.0 - October 11, 2011
+<br>Project org.eclipse.jdt.core v_C15
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_C15">cvs</a>).
+<h2>What's new in this drop</h2>
+
+<h3>Problem Reports Fixed</h3>
+<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=350285">350285</a>
+ASTRewrite destroys formatting on CatchClause#setBody(copyTarget)
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=353474">353474</a>
+type converters should include more annotations
+
+<a name="v_C14"></a>
+<hr><h1>
+Eclipse Platform Build Notes<br>
+Java development tools core</h1>
+Eclipse SDK 3.8.0 - October 5, 2011
+<br>Project org.eclipse.jdt.core v_C14
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_C14">cvs</a>).
+<h2>What's new in this drop</h2>
+
+<h3>Problem Reports Fixed</h3>
+<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=354181">354181</a>
+migrate jdt.core to git
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359831">359831</a>
+Fix messages for &quot;new warning for missing try-with-resources&quot;
+
+<a name="v_C13"></a>
+<hr><h1>
+Eclipse Platform Build Notes<br>
+Java development tools core</h1>
+Eclipse SDK 3.8.0 - October 3, 2011
+<br>Project org.eclipse.jdt.core v_C13
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_C13">cvs</a>).
+<h2>What's new in this drop</h2>
+<ul>
+<li>New Javacore option org.eclipse.jdt.core.JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE to raise a warning or error
+ when a resource of type Closeable or AutoCloseable is not closed locally.
+(see details in bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=349326">349326</a>):
+<pre>
+ /**
+ * Compiler option ID: Reporting a resource that is not closed properly.
+ *
+ * When enabled, the compiler will issue an error or a warning if
+ * a local variable holds a value of type <code>java.lang.AutoCloseable</code> (compliance>=1.7)
+ * or a value of type <code>java.io.Closeable</code> (compliance<=1.6) and if
+ * flow analysis shows that the method <code>close()</code> is not invoked locally on that value.
+ *
+ * Option id: <code>"org.eclipse.jdt.core.compiler.problem.reportUnclosedCloseable"</code>
+ * Possible values: <code>{ "error", "warning", "ignore" }</code>
+ * Default: <code>"warning"</code>
+ *
+ * @since 3.8
+ * @category CompilerOptionID
+ */
+ public static final String COMPILER_PB_UNCLOSED_CLOSEABLE = PLUGIN_ID + ".compiler.problem.unclosedCloseable"; //$NON-NLS-1$
+</pre>
+</li>
+<li>New Javacore option org.eclipse.jdt.core.JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE to raise a warning or error
+ when a resource of type Closeable or AutoCloseable is not definitely closed locally.
+(see details in bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=349326">349326</a>):
+<pre>
+ /**
+ * Compiler option ID: Reporting a resource that may not be closed properly.
+ *
+ * When enabled, the compiler will issue an error or a warning if
+ * a local variable holds a value of type <code>java.lang.AutoCloseable</code> (compliance>=1.7)
+ * or a value of type <code>java.io.Closeable</code> (compliance<=1.6) and if
+ * flow analysis shows that the method <code>close()</code> is
+ * not invoked locally on that value for all execution paths.
+ *
+ * Option id: <code>"org.eclipse.jdt.core.compiler.problem.reportPotentiallyUnclosedCloseable"</code>
+ * Possible values: <code>{ "error", "warning", "ignore" }</code>
+ * Default: <code>"ignore"</code>
+ *
+ * @since 3.8
+ * @category CompilerOptionID
+ */
+ public static final String COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE = PLUGIN_ID + ".compiler.problem.potentiallyUnclosedCloseable"; //$NON-NLS-1$
+</pre>
+</li>
+<li>New Javacore option org.eclipse.jdt.core.JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE to raise a warning or error
+ when a resource of type AutoCloseable is closed explicitly rather than using a try-with-resources block.
+(see details in bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=349326">349326</a>):
+<pre>
+ /**
+ * Compiler option ID: Reporting a resource that is not managed by try-with-resources.
+ *
+ * When enabled, the compiler will issue an error or a warning if a local variable
+ * holds a value of type <code>java.lang.AutoCloseable</code>, and if the method
+ * <code>close()</code> is explicitly invoked on that resource, but the resource is
+ * not managed by a try-with-resources block.
+ *
+ * Option id: <code>"org.eclipse.jdt.core.compiler.problem.reportPotentiallyUnclosedCloseable"</code>
+ * Possible values: <code>{ "error", "warning", "ignore" }</code>
+ * Default: <code>"ignore"</code>
+ *
+ * @since 3.8
+ * @category CompilerOptionID
+ */
+ public static final String COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE = PLUGIN_ID + ".compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359495">359495</a>
+[1.7][compiler] VerifyError in try-finally block with lock encompassing for-each block and unlock in finally clause
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=161129">161129</a>
+[batch][compiler] Add -warn:all to report all warnings
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359646">359646</a>
+Formatter fails silently if Java source contains 0x8000000000000000L
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=256796">256796</a>
+[compiler] dead code detection: &quot;if (DEBUG) return;&quot; should also be trivial IF stmt
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359334">359334</a>
+Analysis for resource leak warnings does not consider exceptions as method exit points
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=359362">359362</a>
+FUP of bug 349326: Resource leak on non-Closeable resource.
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=348186">348186</a>
+[compiler] Improve wording for the warning for masked/hidden catch block
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=355838">355838</a>
+[compiler] ecj compiles the code that javac6 rejects
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=349326">349326</a>
+[1.7] new warning for missing try-with-resources
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=354502">354502</a>
+Incorrect Compiler Warning: &quot;Method can be declared as static&quot;
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=241834">241834</a>
+[search] ClassCastException during move class refactoring
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=358827">358827</a>
+[1.7] exception analysis for t-w-r spoils null analysis
+
+<a name="v_C12"></a>
+<hr><h1>
+Eclipse Platform Build Notes<br>
+Java development tools core</h1>
+Eclipse SDK 3.8.0 - September 23, 2011
+<br>Project org.eclipse.jdt.core v_C12
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_C12">cvs</a>).
+<h2>What's new in this drop</h2>
+<ul>
+<li>Tagging to prepare for the git migration</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+
+<a name="v_C11"></a>
+<hr><h1>
+Eclipse Platform Build Notes<br>
+Java development tools core</h1>
+Eclipse SDK 3.8.0 - September 20, 2011
+<br>Project org.eclipse.jdt.core v_C11
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_C11">cvs</a>).
+<h2>What's new in this drop</h2>
+
+<h3>Problem Reports Fixed</h3>
+<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=357110">357110</a>
+Problem with inner classes referenced from jars or class folders: &quot;The type ... cannot be resolved&quot;
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=357471">357471</a>
+ASTParser cannot resolve binding of PackageDeclaration if class name is equal to the first segment of the package name
+
<a name="v_C10"></a>
<hr><h1>
Eclipse Platform Build Notes<br>
@@ -66,7 +453,7 @@ Eclipse SDK 3.8.0 - September 9, 2011
<h3>Problem Reports Fixed</h3>
<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=354332">354332</a>
-DeltaProcessor exhibits O(N&and;2) behavior
+DeltaProcessor exhibits O(N^2) behavior
<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=355605">355605</a>
NPE in HierarchyResolver
<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=347396">347396</a>
@@ -244,7 +631,7 @@ Eclipse SDK 3.8.0 - July 27, 2011
<li>Added a new API in CompletionProposal to tell whether it diamond operator can be used (see bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=351444">351444</a> for details):
<pre>
/**
- * Returns whether it is safe to use the '<>' (diamond) operator in place of explicitly specifying
+ * Returns whether it is safe to use the '&lt;&gt;' (diamond) operator in place of explicitly specifying
* type arguments for this proposal.
*
* This is only relevant for source level 1.7 or greater.
@@ -263,7 +650,7 @@ usage of type arguments when diamond operator can be used instead. (see details
/**
* Compiler option ID: Reporting redundant specification of type arguments in class instance creation expressions.
* When enabled, the compiler will issue an error or a warning if type arguments are used in a class instance creation,
- * when the '<>' operator can be used instead.
+ * when the '&lt;&gt;' operator can be used instead.
*
* This option only has an effect if the compiler compliance is 1.7 or greater.
*
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index fd46fdb80..dd7a81c0a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -117,7 +117,12 @@
* Benjamin Muskalla - added the following constants
* MissingSynchronizedModifierInInheritedMethod
* Stephan Herrmann - added the following constants
- * UnusedObjectAllocation
+ * UnusedObjectAllocation
+ * PotentiallyUnclosedCloseable
+ * PotentiallyUnclosedCloseableAtExit
+ * UnclosedCloseable
+ * UnclosedCloseableAtExit
+ * ExplicitlyClosedAutoCloseable
*
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
@@ -1400,6 +1405,18 @@ void setSourceStart(int sourceStart);
int DiamondNotBelow17 = TypeRelated + 883;
/** @since 3.7.1 */
int RedundantSpecificationOfTypeArguments = TypeRelated + 884;
+ /** @since 3.8 */
+ int PotentiallyUnclosedCloseable = Internal + 885;
+ /** @since 3.8 */
+ int PotentiallyUnclosedCloseableAtExit = Internal + 886;
+ /** @since 3.8 */
+ int UnclosedCloseable = Internal + 887;
+ /** @since 3.8 */
+ int UnclosedCloseableAtExit = Internal + 888;
+ /** @since 3.8 */
+ int ExplicitlyClosedAutoCloseable = Internal + 889;
+ /** @since 3.8 */
+ int SwitchOnEnumNotBelow15 = TypeRelated + 890; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=360317
/**
* External problems -- These are problems defined by other plugins
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index 4d03cf3ea..e4d93c8b6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -16,8 +16,6 @@ import java.util.List;
import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
-import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
@@ -211,8 +209,6 @@ public abstract class AbstractMethodDeclaration
}
}
- public abstract void analyseCode(ClassScope classScope, InitializationFlowContext initializationContext, FlowInfo info);
-
/**
* Bind and add argument's binding into the scope of the method
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 0469e159b..8bd0d348e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -10,6 +10,7 @@
* Stephan Herrmann - Contributions for
* bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
* bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -81,6 +82,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
// process arguments
if (this.arguments != null) {
for (int i = 0, count = this.arguments.length; i < count; i++) {
+ // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
+ flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
flowInfo =
this.arguments[i]
.analyseCode(currentScope, flowContext, flowInfo)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
index ebad17f3b..9b1210481 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
index 95d873c10..d874749d0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
@@ -12,6 +12,7 @@
* bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
* bug 292478 - Report potentially null across variable assignment
* bug 335093 - [compiler][null] minimal hook for future null annotation support
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -78,6 +79,16 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
flowInfo = ((Reference) this.lhs)
.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
.unconditionalInits();
+ if (local != null) {
+ LocalVariableBinding previousTrackerBinding = null;
+ if (local.closeTracker != null) {
+ // Assigning to a variable already holding an AutoCloseable, has it been closed before?
+ previousTrackerBinding = local.closeTracker.binding;
+ if (!flowInfo.isDefinitelyNull(local)) // only if previous value may be non-null
+ local.closeTracker.recordErrorLocation(this, flowInfo.nullStatus(previousTrackerBinding));
+ }
+ FakedTrackingVariable.handleResourceAssignment(flowInfo, this, this.expression, local, previousTrackerBinding);
+ }
int nullStatus = this.expression.nullStatus(flowInfo);
if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
if (nullStatus == FlowInfo.NULL) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
index 92c1e5dd3..28fd5abc3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -45,10 +46,12 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
int complaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED;
for (int i = 0, max = this.statements.length; i < max; i++) {
Statement stat = this.statements[i];
- if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel)) < Statement.COMPLAINED_UNREACHABLE) {
+ if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) {
flowInfo = stat.analyseCode(this.scope, flowContext, flowInfo);
}
}
+ if (this.explicitDeclarations > 0) // if block has its own scope analyze tracking vars now:
+ this.scope.checkUnclosedCloseables(flowInfo, null, null);
return flowInfo;
}
/**
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
index 3c5991878..cc390d333 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -72,7 +72,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
targetContext.recordBreakFrom(flowInfo);
break;
}
- } while ((traversedContext = traversedContext.parent) != null);
+ } while ((traversedContext = traversedContext.getLocalParent()) != null);
// resize subroutines
if (subCount != this.subroutines.length) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
index cf4ba6101..30f8d24be 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
@@ -13,6 +13,7 @@
* bug 292478 - Report potentially null across variable assignment
* bug 324178 - [null] ConditionalExpression.nullStatus(..) doesn't take into account the analysis of condition itself
* bug 354554 - [null] conditional with redundant condition yields weak error message
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -75,7 +76,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
trueFlowInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD);
}
if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) {
- this.valueIfTrue.complainIfUnreachable(trueFlowInfo, currentScope, initialComplaintLevel);
+ this.valueIfTrue.complainIfUnreachable(trueFlowInfo, currentScope, initialComplaintLevel, false);
}
}
this.trueInitStateIndex = currentScope.methodScope().recordInitializationStates(trueFlowInfo);
@@ -88,7 +89,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
falseFlowInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD);
}
if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) {
- this.valueIfFalse.complainIfUnreachable(falseFlowInfo, currentScope, initialComplaintLevel);
+ this.valueIfFalse.complainIfUnreachable(falseFlowInfo, currentScope, initialComplaintLevel, true);
}
}
this.falseInitStateIndex = currentScope.methodScope().recordInitializationStates(falseFlowInfo);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
index 75a1d9e41..cf7c99194 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
@@ -7,7 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for Bug 343713 - [compiler] bogus line number in constructor of inner class in 1.5 compliance
+ * Stephan Herrmann - Contributions for
+ * bug 343713 - [compiler] bogus line number in constructor of inner class in 1.5 compliance
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -79,18 +81,9 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
public ConstructorDeclaration(CompilationResult compilationResult){
super(compilationResult);
}
-
-/**
- * @see org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration#analyseCode(org.eclipse.jdt.internal.compiler.lookup.ClassScope, org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext, org.eclipse.jdt.internal.compiler.flow.FlowInfo)
- * @deprecated use instead {@link #analyseCode(ClassScope, InitializationFlowContext, FlowInfo, int)}
- */
-public void analyseCode(ClassScope classScope, InitializationFlowContext initializerFlowContext, FlowInfo flowInfo) {
- analyseCode(classScope, initializerFlowContext, flowInfo, FlowInfo.REACHABLE);
-}
-
/**
* The flowInfo corresponds to non-static field initialization infos. It may be unreachable (155423), but still the explicit constructor call must be
- * analysed as reachable, since it will be generated in the end.
+ * analyzed as reachable, since it will be generated in the end.
*/
public void analyseCode(ClassScope classScope, InitializationFlowContext initializerFlowContext, FlowInfo flowInfo, int initialReachMode) {
if (this.ignoreFurtherInvestigation)
@@ -130,7 +123,7 @@ public void analyseCode(ClassScope classScope, InitializationFlowContext initial
// force called constructor to be analyzed:
MethodBinding selfCall = this.constructorCall.binding;
if (selfCall.declaringClass == this.binding.declaringClass)
- selfCall.sourceMethod().analyseCode(classScope, initializerFlowContext, flowInfo.copy());
+ ((ConstructorDeclaration)selfCall.sourceMethod()).analyseCode(classScope, initializerFlowContext, flowInfo.copy(), flowInfo.reachMode());
boolean calledHere = MethodModel.callsBaseCtor(this.binding);
boolean calledIndirectly = MethodModel.callsBaseCtor(selfCall);
@@ -276,7 +269,7 @@ public void analyseCode(ClassScope classScope, InitializationFlowContext initial
int complaintLevel = (nonStaticFieldInfoReachMode & FlowInfo.UNREACHABLE) == 0 ? Statement.NOT_COMPLAINED : Statement.COMPLAINED_FAKE_REACHABLE;
for (int i = 0, count = this.statements.length; i < count; i++) {
Statement stat = this.statements[i];
- if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel)) < Statement.COMPLAINED_UNREACHABLE) {
+ if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) {
flowInfo = stat.analyseCode(this.scope, constructorContext, flowInfo);
}
}
@@ -663,6 +656,7 @@ public boolean isRecursive(ArrayList visited) {
ConstructorDeclaration targetConstructor =
((ConstructorDeclaration)this.scope.referenceType().declarationOf(this.constructorCall.binding.original()));
+ if (targetConstructor == null) return false; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=358762
if (this == targetConstructor) return true; // direct case
if (visited == null) { // lazy allocation
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java
index 1641bc5a9..475fef21f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -75,7 +75,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
targetContext.recordContinueFrom(flowContext, flowInfo);
break;
}
- } while ((traversedContext = traversedContext.parent) != null);
+ } while ((traversedContext = traversedContext.getLocalParent()) != null);
// resize subroutines
if (subCount != this.subroutines.length) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java
index d6cbd10ca..904e56406 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -29,12 +30,12 @@ public class EmptyStatement extends Statement {
}
// Report an error if necessary
- public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int complaintLevel) {
+ public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int complaintLevel, boolean endOfBlock) {
// before 1.4, empty statements are tolerated anywhere
if (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_4) {
return complaintLevel;
}
- return super.complainIfUnreachable(flowInfo, scope, complaintLevel);
+ return super.complainIfUnreachable(flowInfo, scope, complaintLevel, endOfBlock);
}
public void generateCode(BlockScope currentScope, CodeStream codeStream){
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java
new file mode 100644
index 000000000..ee1304749
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2011 GK Software AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.flow.FlowContext;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+
+/**
+ * A faked local variable declaration used for keeping track of data flows of a
+ * special variable. Certain events will be recorded by changing the null info
+ * for this variable.
+ *
+ * See bug 349326 - [1.7] new warning for missing try-with-resources
+ */
+public class FakedTrackingVariable extends LocalDeclaration {
+
+ // a call to close() was seen at least on one path:
+ private static final int CLOSE_SEEN = 1;
+ // the resource was passed to outside code (arg in method/ctor call or as a return value from this method):
+ private static final int PASSED_TO_OUTSIDE = 2;
+ // If close() is invoked from a nested method (inside a local type) report remaining problems only as potential:
+ private static final int CLOSED_IN_NESTED_METHOD = 4;
+ // a location independent issue has been reported already against this resource:
+ private static final int REPORTED = 8;
+
+ /**
+ * Bitset of {@link #CLOSE_SEEN}, {@link #PASSED_TO_OUTSIDE}, {@link #CLOSED_IN_NESTED_METHOD} and {@link #REPORTED}.
+ */
+ private int globalClosingState = 0;
+
+ MethodScope methodScope; // designates the method declaring this variable
+
+ public LocalVariableBinding originalBinding; // the real local being tracked
+
+ HashMap recordedLocations; // initially null, ASTNode -> Integer
+
+
+ public FakedTrackingVariable(LocalVariableBinding original, Statement location) {
+ super(original.name, location.sourceStart, location.sourceEnd);
+ this.type = new SingleTypeReference(
+ TypeConstants.OBJECT,
+ ((long)this.sourceStart <<32)+this.sourceEnd);
+ this.methodScope = original.declaringScope.methodScope();
+ this.originalBinding = original;
+ resolve(original.declaringScope);
+ }
+
+ public void generateCode(BlockScope currentScope, CodeStream codeStream)
+ { /* NOP - this variable is completely dummy, ie. for analysis only. */ }
+
+ public void resolve (BlockScope scope) {
+ // only need the binding, which is used as reference in FlowInfo methods.
+ this.binding = new LocalVariableBinding(
+ this.name,
+ scope.getJavaLangObject(), // dummy, just needs to be a reference type
+ 0,
+ false);
+ this.binding.setConstant(Constant.NotAConstant);
+ this.binding.useFlag = LocalVariableBinding.USED;
+ // use a free slot without assigning it:
+ this.binding.id = scope.registerTrackingVariable(this);
+ }
+
+ /**
+ * If expression resolves to a local variable binding of type AutoCloseable,
+ * answer the variable that tracks closing of that local, creating it if needed.
+ * @param expression
+ * @return a new {@link FakedTrackingVariable} or null.
+ */
+ public static FakedTrackingVariable getCloseTrackingVariable(Expression expression) {
+ if (expression instanceof SingleNameReference) {
+ SingleNameReference name = (SingleNameReference) expression;
+ if (name.binding instanceof LocalVariableBinding) {
+ LocalVariableBinding local = (LocalVariableBinding)name.binding;
+ if (local.closeTracker != null)
+ return local.closeTracker;
+ if (local.isParameter() || !isAutoCloseable(expression.resolvedType))
+ return null;
+ // tracking var doesn't yet exist. This happens in finally block
+ // which is analyzed before the corresponding try block
+ Statement location = local.declaration;
+ return local.closeTracker = new FakedTrackingVariable(local, location);
+ }
+ }
+ return null;
+ }
+
+ /** if 'invocationSite' is a call to close() that has a registered tracking variable, answer that variable's binding. */
+ public static LocalVariableBinding getTrackerForCloseCall(ASTNode invocationSite) {
+ if (invocationSite instanceof MessageSend) {
+ MessageSend send = (MessageSend) invocationSite;
+ if (CharOperation.equals(TypeConstants.CLOSE, send.selector) && send.receiver instanceof SingleNameReference) {
+ Binding receiverBinding = ((SingleNameReference)send.receiver).binding;
+ if (receiverBinding instanceof LocalVariableBinding) {
+ FakedTrackingVariable trackingVariable = ((LocalVariableBinding)receiverBinding).closeTracker;
+ if (trackingVariable != null)
+ return trackingVariable.binding;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Check if the rhs of an assignment or local declaration is an (Auto)Closeable.
+ * If so create or re-use a tracking variable, and wire and initialize everything.
+ */
+ public static void handleResourceAssignment(FlowInfo flowInfo, Statement location, Expression rhs, LocalVariableBinding local,
+ LocalVariableBinding previousTrackerBinding)
+ {
+ if (isAutoCloseable(rhs.resolvedType)) {
+ // new value is AutoCloseable, start tracking, possibly re-using existing tracker var:
+
+ FakedTrackingVariable rhsTrackVar = getCloseTrackingVariable(rhs);
+ if (rhsTrackVar != null) { // 1. share tracking variable with RHS?
+ local.closeTracker = rhsTrackVar;
+ // keep null-status unchanged across this assignment
+ } else if (previousTrackerBinding != null) { // 2. re-use tracking variable from the LHS?
+ // re-assigning from a fresh, mark as not-closed again:
+ flowInfo.markAsDefinitelyNull(previousTrackerBinding);
+ } else { // 3. no re-use, create a fresh tracking variable:
+ local.closeTracker = new FakedTrackingVariable(local, location);
+ // a fresh resource, mark as not-closed:
+ flowInfo.markAsDefinitelyNull(local.closeTracker.binding);
+// TODO(stephan): this might be useful, but I could not find a test case for it:
+// if (flowContext.initsOnFinally != null)
+// flowContext.initsOnFinally.markAsDefinitelyNonNull(trackerBinding);
+ }
+ }
+ }
+
+ /** Answer wither the given type binding is a subtype of java.lang.AutoCloseable. */
+ public static boolean isAutoCloseable(TypeBinding typeBinding) {
+ return typeBinding instanceof ReferenceBinding
+ && ((ReferenceBinding)typeBinding).hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable);
+ }
+
+ /** Mark that this resource is closed locally. */
+ public void markClose(FlowInfo flowInfo, FlowContext flowContext) {
+ flowInfo.markAsDefinitelyNonNull(this.binding);
+ this.globalClosingState |= CLOSE_SEEN;
+//TODO(stephan): this might be useful, but I could not find a test case for it:
+// if (flowContext.initsOnFinally != null)
+// flowContext.initsOnFinally.markAsDefinitelyNonNull(this.binding);
+ }
+
+ /** Mark that this resource is closed from a nested method (inside a local class). */
+ public void markClosedInNestedMethod() {
+ this.globalClosingState |= CLOSED_IN_NESTED_METHOD;
+ }
+
+ /**
+ * Mark that this resource is passed to some outside code
+ * (as argument to a method/ctor call or as a return value from the current method),
+ * and thus should be considered as potentially closed.
+ */
+ public static FlowInfo markPassedToOutside(BlockScope scope, Expression expression, FlowInfo flowInfo) {
+ FakedTrackingVariable trackVar = getCloseTrackingVariable(expression);
+ if (trackVar != null) {
+ trackVar.globalClosingState |= PASSED_TO_OUTSIDE;
+ if (scope.methodScope() != trackVar.methodScope)
+ trackVar.globalClosingState |= CLOSED_IN_NESTED_METHOD;
+ // insert info that the tracked resource *may* be closed (by the target method, i.e.)
+ FlowInfo infoResourceIsClosed = flowInfo.copy();
+ infoResourceIsClosed.markAsDefinitelyNonNull(trackVar.binding);
+ return FlowInfo.conditional(flowInfo, infoResourceIsClosed);
+ }
+ return flowInfo;
+ }
+
+ public void recordErrorLocation(ASTNode location, int nullStatus) {
+ if (this.recordedLocations == null)
+ this.recordedLocations = new HashMap();
+ this.recordedLocations.put(location, new Integer(nullStatus));
+ }
+
+ public boolean reportRecordedErrors(Scope scope) {
+ if (this.globalClosingState == 0) {
+ reportError(scope.problemReporter(), null, FlowInfo.NULL);
+ return true;
+ }
+ boolean hasReported = false;
+ if (this.recordedLocations != null) {
+ Iterator locations = this.recordedLocations.entrySet().iterator();
+ while (locations.hasNext()) {
+ Map.Entry entry = (Entry) locations.next();
+ reportError(scope.problemReporter(), (ASTNode)entry.getKey(), ((Integer)entry.getValue()).intValue());
+ hasReported = true;
+ }
+ }
+ return hasReported;
+ }
+
+ public void reportError(ProblemReporter problemReporter, ASTNode location, int nullStatus) {
+ if (nullStatus == FlowInfo.NULL) {
+ if ((this.globalClosingState & CLOSED_IN_NESTED_METHOD) != 0)
+ problemReporter.potentiallyUnclosedCloseable(this, location);
+ else
+ problemReporter.unclosedCloseable(this, location);
+ } else if (nullStatus == FlowInfo.POTENTIALLY_NULL) {
+ problemReporter.potentiallyUnclosedCloseable(this, location);
+ }
+ }
+
+ public void reportExplicitClosing(ProblemReporter problemReporter) {
+ if ((this.globalClosingState & REPORTED) == 0) {
+ this.globalClosingState |= REPORTED;
+ problemReporter.explicitlyClosedAutoCloseable(this);
+ }
+ }
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
index 7f0b9b154..961180d42 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
@@ -7,7 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * Stephan Herrmann - Contributions for
+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Technical University Berlin - extended API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -139,7 +141,7 @@ public class ForStatement extends Statement {
actionInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD);
}
}
- if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel) < Statement.COMPLAINED_UNREACHABLE) {
+ if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) {
actionInfo = this.action.analyseCode(this.scope, loopingContext, actionInfo).unconditionalInits();
}
@@ -216,6 +218,17 @@ public class ForStatement extends Statement {
exitBranch,
isConditionOptimizedFalse,
!isConditionTrue /*for(;;){}while(true); unreachable(); */);
+ // Variables initialized only for the purpose of the for loop can be removed for further flow info
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=359495
+ if (this.initializations != null) {
+ for (int i = 0; i < this.initializations.length; i++) {
+ Statement init = this.initializations[i];
+ if (init instanceof LocalDeclaration) {
+ LocalVariableBinding binding = ((LocalDeclaration) init).binding;
+ mergedInfo.resetAssignmentInfo(binding);
+ }
+ }
+ }
this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
return mergedInfo;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
index 3a7b16c20..e2f171173 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
* Technical University Berlin - extended API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -112,13 +113,13 @@ public class ForeachStatement extends Statement {
if (!(this.action == null || (this.action.isEmptyBlock()
&& currentScope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_3))) {
- if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel) < Statement.COMPLAINED_UNREACHABLE) {
+ if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) {
actionInfo = this.action.analyseCode(this.scope, loopingContext, actionInfo).unconditionalCopy();
}
// code generation can be optimized when no need to continue in the loop
exitBranch = flowInfo.unconditionalCopy().
- addInitializationsFrom(condInfo.initsWhenFalse());
+ addNullInfoFrom(condInfo.initsWhenFalse());
// TODO (maxime) no need to test when false: can optimize (same for action being unreachable above)
if ((actionInfo.tagBits & loopingContext.initsOnContinue.tagBits &
FlowInfo.UNREACHABLE_OR_DEAD) != 0) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
index 7d0788e38..4cb445da4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
@@ -7,7 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * Stephan Herrmann - Contributions for
+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * bug 349326 - [1.7] new warning for missing try-with-resources
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -84,12 +86,13 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
// No need if the whole if-else construct itself lies in unreachable code
this.bits |= ASTNode.IsElseStatementUnreachable;
}
+ boolean reportDeadCodeForKnownPattern = !isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement;
if (this.thenStatement != null) {
// Save info for code gen
this.thenInitStateIndex = currentScope.methodScope().recordInitializationStates(thenFlowInfo);
if (isConditionOptimizedFalse || ((this.bits & ASTNode.IsThenStatementUnreachable) != 0)) {
- if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) {
- this.thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, initialComplaintLevel);
+ if (reportDeadCodeForKnownPattern) {
+ this.thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, initialComplaintLevel, false);
} else {
// its a known coding pattern which should be tolerated by dead code analysis
// according to isKnowDeadCodePattern()
@@ -117,8 +120,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
// Save info for code gen
this.elseInitStateIndex = currentScope.methodScope().recordInitializationStates(elseFlowInfo);
if (isConditionOptimizedTrue || ((this.bits & ASTNode.IsElseStatementUnreachable) != 0)) {
- if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) {
- this.elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, initialComplaintLevel);
+ if (reportDeadCodeForKnownPattern) {
+ this.elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, initialComplaintLevel, false);
} else {
// its a known coding pattern which should be tolerated by dead code analysis
// according to isKnowDeadCodePattern()
@@ -127,6 +130,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
}
elseFlowInfo = this.elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
}
+ // process AutoCloseable resources closed in only one branch:
+ currentScope.correlateTrackingVarsIfElse(thenFlowInfo, elseFlowInfo);
// merge THEN & ELSE initializations
FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranchesIfElse(
thenFlowInfo,
@@ -135,7 +140,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
isConditionOptimizedFalse,
true /*if(true){ return; } fake-reachable(); */,
flowInfo,
- this);
+ this,
+ reportDeadCodeForKnownPattern);
this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
return mergedInfo;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
index 2ea75004c..18990568b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
@@ -12,6 +12,7 @@
* bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
* bug 292478 - Report potentially null across variable assignment
* bug 335093 - [compiler][null] minimal hook for future null annotation support
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -120,6 +121,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
this.initialization
.analyseCode(currentScope, flowContext, flowInfo)
.unconditionalInits();
+ FakedTrackingVariable.handleResourceAssignment(flowInfo, this, this.initialization, this.binding, null);
int nullStatus = this.initialization.nullStatus(flowInfo);
if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes
this.bits |= FirstAssignmentToLocal;
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 f201f4a0b..8a9a9194f 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
@@ -9,7 +9,9 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752)
- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * Stephan Herrmann - Contributions for
+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -47,6 +49,7 @@ import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
@@ -147,6 +150,18 @@ public class MessageSend extends Expression implements InvocationSite {
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
boolean nonStatic = !this.binding.isStatic();
flowInfo = this.receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits();
+ // recording the closing of AutoCloseable resources:
+ if (CharOperation.equals(TypeConstants.CLOSE, this.selector))
+ {
+ FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.receiver);
+ if (trackingVariable != null) { // null happens if receiver is not a local variable or not an AutoCloseable
+ if (trackingVariable.methodScope == currentScope.methodScope()) {
+ trackingVariable.markClose(flowInfo, flowContext);
+ } else {
+ trackingVariable.markClosedInNestedMethod();
+ }
+ }
+ }
if (nonStatic) {
this.receiver.checkNPE(currentScope, flowContext, flowInfo);
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
@@ -167,6 +182,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
}
+ // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
+ flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
index 85cb80304..2f9645090 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
@@ -8,6 +8,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -21,8 +22,8 @@ import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext;
+import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
-import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
@@ -77,7 +78,7 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
super(compilationResult);
}
- public void analyseCode(ClassScope classScope, InitializationFlowContext initializationContext, FlowInfo flowInfo) {
+ public void analyseCode(ClassScope classScope, FlowContext flowContext, FlowInfo flowInfo) {
// starting of the code analysis for methods
if (this.ignoreFurtherInvestigation)
return;
@@ -121,7 +122,7 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
ExceptionHandlingFlowContext methodContext =
new ExceptionHandlingFlowContext(
- initializationContext,
+ flowContext,
this,
this.binding.thrownExceptions,
null,
@@ -150,7 +151,7 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
int complaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) == 0 ? Statement.NOT_COMPLAINED : Statement.COMPLAINED_FAKE_REACHABLE;
for (int i = 0, count = this.statements.length; i < count; i++) {
Statement stat = this.statements[i];
- if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel)) < Statement.COMPLAINED_UNREACHABLE) {
+ if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) {
flowInfo = stat.analyseCode(this.scope, methodContext, flowInfo);
}
}
@@ -187,6 +188,7 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
}
}
+ this.scope.checkUnclosedCloseables(flowInfo, null/*don't report against a specific location*/, null);
} catch (AbortMethod e) {
this.ignoreFurtherInvestigation = true;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
index c9e36db40..f376efead 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
@@ -7,7 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * Stephan Herrmann - Contributions for
+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -128,6 +130,11 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
// analyse the enclosing instance
if (this.enclosingInstance != null) {
flowInfo = this.enclosingInstance.analyseCode(currentScope, flowContext, flowInfo);
+ } else {
+ if (this.binding.declaringClass.superclass().isMemberType() && !this.binding.declaringClass.superclass().isStatic()) {
+ // creating an anonymous type of a non-static member type without an enclosing instance of parent type
+ currentScope.resetEnclosingMethodStaticFlag();
+ }
}
// check captured variables are initialized in current context (26134)
@@ -141,6 +148,8 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
// process arguments
if (this.arguments != null) {
for (int i = 0, count = this.arguments.length; i < count; i++) {
+ // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
+ flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo);
if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
index 8d97f740f..b8f74828b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
@@ -7,7 +7,10 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * Stephan Herrmann - Contributions for
+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * bug 349326 - [1.7] new warning for missing try-with-resources
+ * bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
* Technical University Berlin - extended API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -41,14 +44,23 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
// lookup the label, this should answer the returnContext
+ MethodScope methodScope = currentScope.methodScope();
if (this.expression != null) {
flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo);
if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
this.expression.checkNPE(currentScope, flowContext, flowInfo);
}
+ FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.expression);
+ if (trackingVariable != null) {
+ if (methodScope != trackingVariable.methodScope)
+ trackingVariable.markClosedInNestedMethod();
+ // don't report issues concerning this local, since by returning
+ // the method passes the responsibility to the caller:
+ currentScope.removeTrackingVar(trackingVariable);
+ }
}
this.initStateIndex =
- currentScope.methodScope().recordInitializationStates(flowInfo);
+ methodScope.recordInitializationStates(flowInfo);
// compute the return sequence (running the finally blocks)
FlowContext traversedContext = flowContext;
int subCount = 0;
@@ -85,14 +97,14 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
}
saveValueNeeded = true;
this.initStateIndex =
- currentScope.methodScope().recordInitializationStates(flowInfo);
+ methodScope.recordInitializationStates(flowInfo);
}
}
} else if (traversedContext instanceof InitializationFlowContext) {
currentScope.problemReporter().cannotReturnInInitializer(this);
return FlowInfo.DEAD_END;
}
- } while ((traversedContext = traversedContext.parent) != null);
+ } while ((traversedContext = traversedContext.getLocalParent()) != null);
// resize subroutines
if ((this.subroutines != null) && (subCount != this.subroutines.length)) {
@@ -110,6 +122,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
this.expression.bits |= ASTNode.IsReturnedValue;
}
}
+ currentScope.checkUnclosedCloseables(flowInfo, this, currentScope);
return FlowInfo.DEAD_END;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
index 5a3bc4c2a..a45b8447e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
@@ -8,7 +8,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 335093 - [compiler][null] minimal hook for future null annotation support
+ * Stephan Herrmann - Contributions for
+ * bug 335093 - [compiler][null] minimal hook for future null annotation support
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -82,7 +84,7 @@ public void branchChainTo(BranchLabel label) {
// Report an error if necessary (if even more unreachable than previously reported
// complaintLevel = 0 if was reachable up until now, 1 if fake reachable (deadcode), 2 if fatal unreachable (error)
-public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int previousComplaintLevel) {
+public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int previousComplaintLevel, boolean endOfBlock) {
if ((flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0) {
if ((flowInfo.reachMode() & FlowInfo.UNREACHABLE_OR_DEAD) != 0)
this.bits &= ~ASTNode.IsReachable;
@@ -104,6 +106,8 @@ public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int previo
if (previousComplaintLevel < COMPLAINED_UNREACHABLE) {
/* OT: */ if (shouldReport)
scope.problemReporter().unreachableCode(this);
+ if (endOfBlock)
+ scope.checkUnclosedCloseables(flowInfo, null, null);
}
return COMPLAINED_UNREACHABLE;
} else {
@@ -111,6 +115,8 @@ public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int previo
/* OT: */ if (shouldReport)
// SH}
scope.problemReporter().fakeReachable(this);
+ if (endOfBlock)
+ scope.checkUnclosedCloseables(flowInfo, null, null);
}
return COMPLAINED_FAKE_REACHABLE;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
index 5b171fc00..03c6e80ba 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
@@ -7,7 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * Stephan Herrmann - Contributions for
+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * bug 349326 - [1.7] new warning for missing try-with-resources
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -99,7 +101,7 @@ public class SwitchStatement extends Statement {
} else {
fallThroughState = FALLTHROUGH; // reset below if needed
}
- if ((complaintLevel = statement.complainIfUnreachable(caseInits, this.scope, complaintLevel)) < Statement.COMPLAINED_UNREACHABLE) {
+ if ((complaintLevel = statement.complainIfUnreachable(caseInits, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) {
caseInits = statement.analyseCode(this.scope, switchContext, caseInits);
if (caseInits == FlowInfo.DEAD_END) {
fallThroughState = ESCAPING;
@@ -461,6 +463,9 @@ public class SwitchStatement extends Statement {
break checkType;
} else if (expressionType.isEnum()) {
isEnumSwitch = true;
+ if (upperScope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_5) {
+ upperScope.problemReporter().incorrectSwitchType(this.expression, expressionType); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=360317
+ }
break checkType;
} else if (upperScope.isBoxingCompatibleWith(expressionType, TypeBinding.INT)) {
this.expression.computeConversion(upperScope, TypeBinding.INT, expressionType);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
index 89b1b5f6e..252962940 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -46,6 +47,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
this.exception.checkNPE(currentScope, flowContext, flowInfo);
// need to check that exception thrown is actually caught somewhere
flowContext.checkExceptionHandlers(this.exceptionType, this, flowInfo, currentScope);
+ currentScope.checkUnclosedCloseables(flowInfo, this, currentScope);
return FlowInfo.DEAD_END;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
index 5944bb3f0..0e761c37f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
@@ -7,7 +7,11 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 332637 - Dead Code detection removing code that isn't dead
+ * Stephan Herrmann - Contributions for
+ * bug 332637 - Dead Code detection removing code that isn't dead
+ * bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis
+ * bug 349326 - [1.7] new warning for missing try-with-resources
+ * bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -138,8 +142,14 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
for (int i = 0; i < resourcesLength; i++) {
flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(flowInfo);
- this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
- TypeBinding type = this.resources[i].binding.type;
+ LocalVariableBinding resourceBinding = this.resources[i].binding;
+ resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
+ if (resourceBinding.closeTracker != null) {
+ // this was false alarm, we don't need to track the resource
+ this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker);
+ resourceBinding.closeTracker = null;
+ }
+ TypeBinding type = resourceBinding.type;
if (type != null && type.isValidBinding()) {
ReferenceBinding binding = (ReferenceBinding) type;
MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter
@@ -243,6 +253,14 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
if (subInfo == FlowInfo.DEAD_END) {
this.bits |= ASTNode.IsSubRoutineEscaping;
this.scope.problemReporter().finallyMustCompleteNormally(this.finallyBlock);
+ } else {
+ // for resource analysis we need the finallyInfo in these nested scopes:
+ FlowInfo finallyInfo = subInfo.copy();
+ this.tryBlock.scope.finallyInfo = finallyInfo;
+ if (this.catchBlocks != null) {
+ for (int i = 0; i < this.catchBlocks.length; i++)
+ this.catchBlocks[i].scope.finallyInfo = finallyInfo;
+ }
}
this.subRoutineInits = subInfo;
// process the try block in a context handling the local exceptions.
@@ -264,15 +282,21 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
for (int i = 0; i < resourcesLength; i++) {
flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(flowInfo);
- this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
- TypeBinding type = this.resources[i].binding.type;
+ LocalVariableBinding resourceBinding = this.resources[i].binding;
+ resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
+ if (resourceBinding.closeTracker != null) {
+ // this was false alarm, we don't need to track the resource
+ this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker);
+ resourceBinding.closeTracker = null;
+ }
+ TypeBinding type = resourceBinding.type;
if (type != null && type.isValidBinding()) {
ReferenceBinding binding = (ReferenceBinding) type;
MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter
if (closeMethod != null && closeMethod.returnType.id == TypeIds.T_void) {
ReferenceBinding[] thrownExceptions = closeMethod.thrownExceptions;
for (int j = 0, length = thrownExceptions.length; j < length; j++) {
- handlingContext.checkExceptionHandlers(thrownExceptions[j], this.resources[j], flowInfo, currentScope);
+ handlingContext.checkExceptionHandlers(thrownExceptions[j], this.resources[i], flowInfo, currentScope, true);
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index 816e5adf4..bf4634e42 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -8,6 +8,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for Bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -1178,7 +1179,11 @@ private void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
this.scope.problemReporter().unusedPrivateType(this);
}
}
- InitializationFlowContext initializerContext = new InitializationFlowContext(null, this, flowInfo, flowContext, this.initializerScope);
+ // for local classes we use the flowContext as our parent, but never use an initialization context for this purpose
+ // see Bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
+ FlowContext parentContext = (flowContext instanceof InitializationFlowContext) ? null : flowContext;
+ InitializationFlowContext initializerContext = new InitializationFlowContext(parentContext, this, flowInfo, flowContext, this.initializerScope);
+ // no static initializer in local classes, thus no need to set parent:
InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, flowInfo, flowContext, this.staticInitializerScope);
FlowInfo nonStaticFieldInfo = flowInfo.unconditionalFieldLessCopy();
FlowInfo staticFieldInfo = flowInfo.unconditionalFieldLessCopy();
@@ -1252,8 +1257,9 @@ private void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
continue;
// SH}
if (method.isInitializationMethod()) {
+ // pass down the appropriate initializerContext:
if (method.isStatic()) { // <clinit>
- method.analyseCode(
+ ((Clinit)method).analyseCode(
this.scope,
staticInitializerContext,
staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo));
@@ -1261,7 +1267,8 @@ private void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
((ConstructorDeclaration)method).analyseCode(this.scope, initializerContext, constructorInfo.copy(), flowInfo.reachMode());
}
} else { // regular method
- method.analyseCode(this.scope, null, flowInfo.copy());
+ // pass down the parentContext (NOT an initializer context, see above):
+ ((MethodDeclaration)method).analyseCode(this.scope, parentContext, flowInfo.copy());
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
index c51042e38..e35ea9c0b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
@@ -7,7 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * Stephan Herrmann - Contributions for
+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * bug 349326 - [1.7] new warning for missing try-with-resources
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -113,7 +115,7 @@ public class WhileStatement extends Statement {
currentScope.methodScope().recordInitializationStates(
condInfo.initsWhenTrue());
- if (this.action.complainIfUnreachable(actionInfo, currentScope, initialComplaintLevel) < Statement.COMPLAINED_UNREACHABLE) {
+ if (this.action.complainIfUnreachable(actionInfo, currentScope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) {
actionInfo = this.action.analyseCode(currentScope, loopingContext, actionInfo);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
index 6d9a4e611..ba8c821f6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -79,6 +79,9 @@ public interface ClassFileConstants {
int MethodRefTag = 10;
int InterfaceMethodRefTag = 11;
int NameAndTypeTag = 12;
+ int MethodHandleTag = 15;
+ int MethodTypeTag = 16;
+ int InvokeDynamicTag = 18;
int ConstantMethodRefFixedSize = 5;
int ConstantClassFixedSize = 3;
@@ -91,6 +94,9 @@ public interface ClassFileConstants {
int ConstantStringFixedSize = 3;
int ConstantUtf8FixedSize = 3;
int ConstantNameAndTypeFixedSize = 5;
+ int ConstantMethodHandleFixedSize = 4;
+ int ConstantMethodTypeFixedSize = 3;
+ int ConstantInvokeDynamicFixedSize = 5;
int MAJOR_VERSION_1_1 = 45;
int MAJOR_VERSION_1_2 = 46;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
index 3a9e1630c..d274fc676 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -247,6 +247,19 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit
case ClassFileConstants.NameAndTypeTag :
this.constantPoolOffsets[i] = readOffset;
readOffset += ClassFileConstants.ConstantNameAndTypeFixedSize;
+ break;
+ case ClassFileConstants.MethodHandleTag :
+ this.constantPoolOffsets[i] = readOffset;
+ readOffset += ClassFileConstants.ConstantMethodHandleFixedSize;
+ break;
+ case ClassFileConstants.MethodTypeTag :
+ this.constantPoolOffsets[i] = readOffset;
+ readOffset += ClassFileConstants.ConstantMethodTypeFixedSize;
+ break;
+ case ClassFileConstants.InvokeDynamicTag :
+ this.constantPoolOffsets[i] = readOffset;
+ readOffset += ClassFileConstants.ConstantInvokeDynamicFixedSize;
+ break;
}
}
//{ObjectTeams: store offset
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
index c137b4276..5cb416656 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
@@ -252,4 +252,9 @@ public boolean isMarkedAsNullOrNonNullInAssertExpression(LocalVariableBinding lo
return (this.initsWhenTrue.isMarkedAsNullOrNonNullInAssertExpression(local)
|| this.initsWhenFalse.isMarkedAsNullOrNonNullInAssertExpression(local));
}
+
+public void resetAssignmentInfo(LocalVariableBinding local) {
+ this.initsWhenTrue.resetAssignmentInfo(local);
+ this.initsWhenFalse.resetAssignmentInfo(local);
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
index 059058378..7f7638d01 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
@@ -70,12 +70,12 @@ public void complainOnDeferredChecks(FlowInfo flowInfo, BlockScope scope) {
// any reference reported at this level is removed from the parent context
// where it could also be reported again
if (complained) {
- FlowContext currentContext = this.parent;
+ FlowContext currentContext = this.getLocalParent();
while (currentContext != null) {
//if (currentContext.isSubRoutine()) {
currentContext.removeFinalAssignmentIfAny(this.finalAssignments[i]);
//}
- currentContext = currentContext.parent;
+ currentContext = currentContext.getLocalParent();
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
index e768ff0da..ccb5fb62b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
@@ -7,13 +7,15 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.flow;
import java.util.ArrayList;
+
import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
import org.eclipse.jdt.internal.compiler.ast.Reference;
@@ -197,14 +199,16 @@ public void checkExceptionHandlers(TypeBinding raisedException, ASTNode location
traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
- if (traversedContext instanceof InsideSubRoutineFlowContext) {
- ASTNode node = traversedContext.associatedNode;
- if (node instanceof TryStatement) {
- TryStatement tryStatement = (TryStatement) node;
- flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
+ if (!isExceptionOnAutoClose) {
+ if (traversedContext instanceof InsideSubRoutineFlowContext) {
+ ASTNode node = traversedContext.associatedNode;
+ if (node instanceof TryStatement) {
+ TryStatement tryStatement = (TryStatement) node;
+ flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
+ }
}
}
- traversedContext = traversedContext.parent;
+ traversedContext = traversedContext.getLocalParent();
}
// if reaches this point, then there are some remaining unhandled exception types.
if (isExceptionOnAutoClose) {
@@ -350,7 +354,7 @@ public void checkExceptionHandlers(TypeBinding[] raisedExceptions, ASTNode locat
flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
}
}
- traversedContext = traversedContext.parent;
+ traversedContext = traversedContext.getLocalParent();
}
// if reaches this point, then there are some remaining unhandled exception types.
nextReport: for (int i = 0; i < raisedCount; i++) {
@@ -382,9 +386,9 @@ public FlowInfo getInitsForFinalBlankInitializationCheck(TypeBinding declaringTy
current = initializationContext.initializationParent;
} else if (current instanceof ExceptionHandlingFlowContext) {
ExceptionHandlingFlowContext exceptionContext = (ExceptionHandlingFlowContext) current;
- current = exceptionContext.initializationParent == null ? exceptionContext.parent : exceptionContext.initializationParent;
+ current = exceptionContext.initializationParent == null ? exceptionContext.getLocalParent() : exceptionContext.initializationParent;
} else {
- current = current.parent;
+ current = current.getLocalParent();
}
} while (current != null);
// not found
@@ -408,7 +412,7 @@ public FlowContext getTargetContextForBreakLabel(char[] labelName) {
return current;
return lastNonReturningSubRoutine;
}
- current = current.parent;
+ current = current.getLocalParent();
}
// not found
return null;
@@ -445,7 +449,7 @@ public FlowContext getTargetContextForContinueLabel(char[] labelName) {
// label is found, but not a continuable location
return FlowContext.NotContinuableContext;
}
- current = current.parent;
+ current = current.getLocalParent();
}
// not found
return null;
@@ -464,7 +468,7 @@ public FlowContext getTargetContextForDefaultBreak() {
if (lastNonReturningSubRoutine == null) return current;
return lastNonReturningSubRoutine;
}
- current = current.parent;
+ current = current.getLocalParent();
}
// not found
return null;
@@ -484,12 +488,22 @@ public FlowContext getTargetContextForDefaultContinue() {
return current;
return lastNonReturningSubRoutine;
}
- current = current.parent;
+ current = current.getLocalParent();
}
// not found
return null;
}
+/**
+ * Answer the parent flow context but be careful not to cross the boundary of a nested type,
+ * or null if no such parent exists.
+ */
+public FlowContext getLocalParent() {
+ if (this.associatedNode instanceof AbstractMethodDeclaration || this.associatedNode instanceof TypeDeclaration)
+ return null;
+ return this.parent;
+}
+
public String individualToString() {
return "Flow context"; //$NON-NLS-1$
}
@@ -567,7 +581,7 @@ public void recordSettingFinal(VariableBinding variable, Reference finalReferenc
if (!context.recordFinalAssignment(variable, finalReference)) {
break; // no need to keep going
}
- context = context.parent;
+ context = context.getLocalParent();
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
index fbd9d11f5..177ceaf3b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
@@ -417,12 +417,28 @@ public static UnconditionalFlowInfo mergedOptimizedBranches(
public static UnconditionalFlowInfo mergedOptimizedBranchesIfElse(
FlowInfo initsWhenTrue, boolean isOptimizedTrue,
FlowInfo initsWhenFalse, boolean isOptimizedFalse,
- boolean allowFakeDeadBranch, FlowInfo flowInfo, IfStatement ifStatement) {
+ boolean allowFakeDeadBranch, FlowInfo flowInfo, IfStatement ifStatement,
+ boolean reportDeadCodeInKnownPattern) {
UnconditionalFlowInfo mergedInfo;
if (isOptimizedTrue){
if (initsWhenTrue == FlowInfo.DEAD_END && allowFakeDeadBranch) {
- mergedInfo = initsWhenFalse.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD).
- unconditionalInits();
+ if (!reportDeadCodeInKnownPattern) {
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=256796
+ // do not report code even after if-else as dead as a consequence of analysis done in known dead code pattern
+ // when the CompilerOptions$reportDeadCodeInTrivialIfStatement option is disabled
+ if (ifStatement.elseStatement == null) {
+ mergedInfo = flowInfo.unconditionalInits();
+ } else {
+ mergedInfo = initsWhenFalse.unconditionalInits();
+ if (initsWhenFalse != FlowInfo.DEAD_END) {
+ // let the definitely true status of known dead code pattern not affect the reachability
+ mergedInfo.setReachMode(flowInfo.reachMode());
+ }
+ }
+ } else {
+ mergedInfo = initsWhenFalse.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD).
+ unconditionalInits();
+ }
}
else {
mergedInfo =
@@ -433,8 +449,23 @@ public static UnconditionalFlowInfo mergedOptimizedBranchesIfElse(
}
else if (isOptimizedFalse) {
if (initsWhenFalse == FlowInfo.DEAD_END && allowFakeDeadBranch) {
- mergedInfo = initsWhenTrue.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD).
- unconditionalInits();
+ if (!reportDeadCodeInKnownPattern) {
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=256796
+ // do not report code even after if-else as dead as a consequence of analysis done in known dead code pattern
+ // when the CompilerOptions$reportDeadCodeInTrivialIfStatement option is disabled
+ if (ifStatement.thenStatement == null) {
+ mergedInfo = flowInfo.unconditionalInits();
+ } else {
+ mergedInfo = initsWhenTrue.unconditionalInits();
+ if (initsWhenTrue != FlowInfo.DEAD_END) {
+ // let the definitely false status of known dead code pattern not affect the reachability
+ mergedInfo.setReachMode(flowInfo.reachMode());
+ }
+ }
+ } else {
+ mergedInfo = initsWhenTrue.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD).
+ unconditionalInits();
+ }
}
else {
mergedInfo =
@@ -591,6 +622,12 @@ abstract public void markedAsNullOrNonNullInAssertExpression(LocalVariableBindin
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448
abstract public boolean isMarkedAsNullOrNonNullInAssertExpression(LocalVariableBinding local);
+/**
+ * Resets the definite and potential initialization info for the given local variable
+ * @param local
+ */
+abstract public void resetAssignmentInfo(LocalVariableBinding local);
+
//{ObjectTeams:
public boolean isDefinitelyAssigned(BaseCallTrackingVariable baseCallTrackingVariable)
{
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java
index 33743133f..88ca4e766 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -31,14 +31,14 @@ public LabelFlowContext(FlowContext parent, ASTNode associatedNode, char[] label
void checkLabelValidity(BlockScope scope) {
// check if label was already defined above
- FlowContext current = this.parent;
+ FlowContext current = this.getLocalParent();
while (current != null) {
char[] currentLabelName;
if (((currentLabelName = current.labelName()) != null)
&& CharOperation.equals(currentLabelName, this.labelName)) {
scope.problemReporter().alreadyDefinedLabel(this.labelName, this.associatedNode);
}
- current = current.parent;
+ current = current.getLocalParent();
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
index 886fea6ef..919bb4c2e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
@@ -112,10 +112,10 @@ public void complainOnDeferredFinalChecks(BlockScope scope, FlowInfo flowInfo) {
// any reference reported at this level is removed from the parent context where it
// could also be reported again
if (complained) {
- FlowContext context = this.parent;
+ FlowContext context = this.getLocalParent();
while (context != null) {
context.removeFinalAssignmentIfAny(this.finalAssignments[i]);
- context = context.parent;
+ context = context.getLocalParent();
}
}
}
@@ -396,6 +396,7 @@ public void recordContinueFrom(FlowContext innerFlowContext, FlowInfo flowInfo)
FlowContext inner = innerFlowContext;
while (inner != this && !(inner instanceof LoopingFlowContext)) {
inner = inner.parent;
+ // we know that inner is reachable from this without crossing a type boundary
}
if (inner == this) {
this.upstreamNullFlowInfo.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
index 2e2fef88e..5bc2d8565 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
@@ -14,6 +14,7 @@
* bug 292478 - Report potentially null across variable assignment
* bug 332637 - Dead Code detection removing code that isn't dead
* bug 341499 - [compiler][null] allocate extra bits in all methods of UnconditionalFlowInfo
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -785,7 +786,7 @@ final public boolean isDefinitelyNonNull(LocalVariableBinding local) {
}
int vectorIndex;
if ((vectorIndex = (position / BitCacheSize) - 1)
- >= this.extra[0].length) {
+ >= this.extra[2].length) {
return false; // if not enough room in vector, then not initialized
}
return ((this.extra[2][vectorIndex] & this.extra[4][vectorIndex]
@@ -812,7 +813,7 @@ final public boolean isDefinitelyNull(LocalVariableBinding local) {
}
int vectorIndex;
if ((vectorIndex = (position / BitCacheSize) - 1) >=
- this.extra[0].length) {
+ this.extra[2].length) {
return false; // if not enough room in vector, then not initialized
}
return ((this.extra[2][vectorIndex] & this.extra[3][vectorIndex]
@@ -837,7 +838,7 @@ final public boolean isDefinitelyUnknown(LocalVariableBinding local) {
}
int vectorIndex;
if ((vectorIndex = (position / BitCacheSize) - 1) >=
- this.extra[0].length) {
+ this.extra[2].length) {
return false; // if not enough room in vector, then not initialized
}
return ((this.extra[2][vectorIndex] & this.extra[5][vectorIndex]
@@ -904,7 +905,7 @@ final public boolean isPotentiallyNonNull(LocalVariableBinding local) {
}
int vectorIndex;
if ((vectorIndex = (position / BitCacheSize) - 1) >=
- this.extra[0].length) {
+ this.extra[2].length) {
return false; // if not enough room in vector, then not initialized
}
return ((this.extra[4][vectorIndex]
@@ -930,7 +931,7 @@ final public boolean isPotentiallyNull(LocalVariableBinding local) {
}
int vectorIndex;
if ((vectorIndex = (position / BitCacheSize) - 1) >=
- this.extra[0].length) {
+ this.extra[2].length) {
return false; // if not enough room in vector, then not initialized
}
return ((this.extra[3][vectorIndex]
@@ -956,7 +957,7 @@ final public boolean isPotentiallyUnknown(LocalVariableBinding local) {
}
int vectorIndex;
if ((vectorIndex = (position / BitCacheSize) - 1) >=
- this.extra[0].length) {
+ this.extra[2].length) {
return false; // if not enough room in vector, then not initialized
}
return (this.extra[5][vectorIndex]
@@ -2152,5 +2153,29 @@ private void combineNullStatusChangeInAssertInfo(UnconditionalFlowInfo otherInit
}
}
}
+
+public void resetAssignmentInfo(LocalVariableBinding local) {
+ resetAssignmentInfo(local.id + this.maxFieldCount);
+}
+
+public void resetAssignmentInfo(int position) {
+ if (this != DEAD_END) {
+ // position is zero-based
+ if (position < BitCacheSize) {
+ // use bits
+ long mask;
+ this.definiteInits &= (mask = ~(1L << position));
+ this.potentialInits &= mask;
+ } else {
+ // use extra vector
+ int vectorIndex = (position / BitCacheSize) - 1;
+ if (this.extra == null || vectorIndex >= this.extra[0].length) return; // variable doesnt exist in flow info
+ long mask;
+ this.extra[0][vectorIndex] &=
+ (mask = ~(1L << (position % BitCacheSize)));
+ this.extra[1][vectorIndex] &= mask;
+ }
+ }
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index 621321775..3bcb529ca 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -8,8 +8,10 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Benjamin Muskalla - Contribution for bug 239066
- * Stephan Herrmann - Contribution for bug 236385
- * Stephan Herrmann - Contribution for bug 295551
+ * Stephan Herrmann - Contributions for
+ * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
+ * bug 295551 - Add option to automatically promote all warnings to errors
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -146,6 +148,9 @@ public class CompilerOptions {
public static final String OPTION_ReportMethodCanBeStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic"; //$NON-NLS-1$
public static final String OPTION_ReportMethodCanBePotentiallyStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic"; //$NON-NLS-1$
public static final String OPTION_ReportRedundantSpecificationOfTypeArguments = "org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments"; //$NON-NLS-1$
+ public static final String OPTION_ReportUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.unclosedCloseable"; //$NON-NLS-1$
+ public static final String OPTION_ReportPotentiallyUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable"; //$NON-NLS-1$
+ public static final String OPTION_ReportExplicitlyClosedAutoCloseable = "org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$
//{ObjectTeams: sync with constants in OTDTPlugin:
public static final String OPTION_ReportNotExactlyOneBasecall =
@@ -317,6 +322,10 @@ public class CompilerOptions {
public static final int MethodCanBeStatic = IrritantSet.GROUP2 | ASTNode.Bit5;
public static final int MethodCanBePotentiallyStatic = IrritantSet.GROUP2 | ASTNode.Bit6;
public static final int RedundantSpecificationOfTypeArguments = IrritantSet.GROUP2 | ASTNode.Bit7;
+ // bits 8-10 reserved for https://bugs.eclipse.org/bugs/show_bug.cgi?id=186342
+ public static final int UnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit11;
+ public static final int PotentiallyUnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit12;
+ public static final int ExplicitlyClosedAutoCloseable = IrritantSet.GROUP2 | ASTNode.Bit13;
//{ObjectTeams: OT/J specific problems/irritants:
public static final int OTJFlag = IrritantSet.GROUP3;
@@ -487,8 +496,9 @@ public class CompilerOptions {
"javadoc", //$NON-NLS-1$
"nls", //$NON-NLS-1$
"null", //$NON-NLS-1$
- "restriction", //$NON-NLS-1$
"rawtypes", //$NON-NLS-1$
+ "resource", //$NON-NLS-1$
+ "restriction", //$NON-NLS-1$
"serial", //$NON-NLS-1$
"static-access", //$NON-NLS-1$
"static-method", //$NON-NLS-1$
@@ -682,6 +692,12 @@ public class CompilerOptions {
return OPTION_ReportMethodCanBePotentiallyStatic;
case RedundantSpecificationOfTypeArguments :
return OPTION_ReportRedundantSpecificationOfTypeArguments;
+ case UnclosedCloseable :
+ return OPTION_ReportUnclosedCloseable;
+ case PotentiallyUnclosedCloseable :
+ return OPTION_ReportPotentiallyUnclosedCloseable;
+ case ExplicitlyClosedAutoCloseable :
+ return OPTION_ReportExplicitlyClosedAutoCloseable;
//{ObjectTeams:
case NotExactlyOneBasecall :
return OPTION_ReportNotExactlyOneBasecall;
@@ -891,6 +907,9 @@ public class CompilerOptions {
OPTION_ReportUnusedTypeArgumentsForMethodInvocation,
OPTION_ReportUnusedWarningToken,
OPTION_ReportVarargsArgumentNeedCast,
+ OPTION_ReportUnclosedCloseable,
+ OPTION_ReportPotentiallyUnclosedCloseable,
+ OPTION_ReportExplicitlyClosedAutoCloseable,
//{ObjectTeams:
OPTION_ReportNotExactlyOneBasecall,
OPTION_ReportBaseclassCycle,
@@ -984,6 +1003,10 @@ public class CompilerOptions {
case MethodCanBeStatic :
case MethodCanBePotentiallyStatic :
return "static-method"; //$NON-NLS-1$
+ case PotentiallyUnclosedCloseable:
+ case UnclosedCloseable:
+ case ExplicitlyClosedAutoCloseable:
+ return "resource"; //$NON-NLS-1$
case InvalidJavadoc :
case MissingJavadocComments :
case MissingJavadocTags:
@@ -1082,6 +1105,8 @@ public class CompilerOptions {
case 'r' :
if ("rawtypes".equals(warningToken)) //$NON-NLS-1$
return IrritantSet.RAW;
+ if ("resource".equals(warningToken)) //$NON-NLS-1$
+ return IrritantSet.RESOURCE;
if ("restriction".equals(warningToken)) //$NON-NLS-1$
return IrritantSet.RESTRICTION;
break;
@@ -1282,6 +1307,9 @@ public class CompilerOptions {
optionsMap.put(OPTION_ReportMethodCanBeStatic, getSeverityString(MethodCanBeStatic));
optionsMap.put(OPTION_ReportMethodCanBePotentiallyStatic, getSeverityString(MethodCanBePotentiallyStatic));
optionsMap.put(OPTION_ReportRedundantSpecificationOfTypeArguments, getSeverityString(RedundantSpecificationOfTypeArguments));
+ optionsMap.put(OPTION_ReportUnclosedCloseable, getSeverityString(UnclosedCloseable));
+ optionsMap.put(OPTION_ReportPotentiallyUnclosedCloseable, getSeverityString(PotentiallyUnclosedCloseable));
+ optionsMap.put(OPTION_ReportExplicitlyClosedAutoCloseable, getSeverityString(ExplicitlyClosedAutoCloseable));
//{ObjectTeams:
optionsMap.put(OPTION_Decapsulation, this.decapsulation);
@@ -1744,6 +1772,9 @@ public class CompilerOptions {
if ((optionValue = optionsMap.get(OPTION_ReportMethodCanBeStatic)) != null) updateSeverity(MethodCanBeStatic, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportMethodCanBePotentiallyStatic)) != null) updateSeverity(MethodCanBePotentiallyStatic, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportRedundantSpecificationOfTypeArguments)) != null) updateSeverity(RedundantSpecificationOfTypeArguments, optionValue);
+ if ((optionValue = optionsMap.get(OPTION_ReportUnclosedCloseable)) != null) updateSeverity(UnclosedCloseable, optionValue);
+ if ((optionValue = optionsMap.get(OPTION_ReportPotentiallyUnclosedCloseable)) != null) updateSeverity(PotentiallyUnclosedCloseable, optionValue);
+ if ((optionValue = optionsMap.get(OPTION_ReportExplicitlyClosedAutoCloseable)) != null) updateSeverity(ExplicitlyClosedAutoCloseable, optionValue);
//{ObjectTeams:
if ((optionValue = optionsMap.get(OPTION_ReportNotExactlyOneBasecall)) != null) updateSeverity(NotExactlyOneBasecall, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportBaseclassCycle)) != null) updateSeverity(BaseclassCycle, optionValue);
@@ -2005,6 +2036,9 @@ public class CompilerOptions {
buf.append("\n\t- method can be static: ").append(getSeverityString(MethodCanBeStatic)); //$NON-NLS-1$
buf.append("\n\t- method can be potentially static: ").append(getSeverityString(MethodCanBePotentiallyStatic)); //$NON-NLS-1$
buf.append("\n\t- redundant specification of type arguments: ").append(getSeverityString(RedundantSpecificationOfTypeArguments)); //$NON-NLS-1$
+ buf.append("\n\t- resource is not closed: ").append(getSeverityString(UnclosedCloseable)); //$NON-NLS-1$
+ buf.append("\n\t- resource may not be closed: ").append(getSeverityString(PotentiallyUnclosedCloseable)); //$NON-NLS-1$
+ buf.append("\n\t- resource should be handled by try-with-resources: ").append(getSeverityString(ExplicitlyClosedAutoCloseable)); //$NON-NLS-1$
//{ObjectTeams
buf.append("\n\t- decapsulation : ").append(this.decapsulation); //$NON-NLS-1$
buf.append("\n\t- report if not exactly one basecall in callin method : ").append(getSeverityString(NotExactlyOneBasecall)); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
index 38e7b0672..f10e7ce16 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -68,6 +69,7 @@ public class IrritantSet {
public static final IrritantSet UNUSED = new IrritantSet(CompilerOptions.UnusedLocalVariable);
public static final IrritantSet UNCHECKED = new IrritantSet(CompilerOptions.UncheckedTypeOperation);
public static final IrritantSet UNQUALIFIED_FIELD_ACCESS = new IrritantSet(CompilerOptions.UnqualifiedFieldAccess);
+ public static final IrritantSet RESOURCE = new IrritantSet(CompilerOptions.UnclosedCloseable);
public static final IrritantSet JAVADOC = new IrritantSet(CompilerOptions.InvalidJavadoc);
public static final IrritantSet COMPILER_DEFAULT_ERRORS = new IrritantSet(0); // no optional error by default
@@ -174,7 +176,8 @@ public class IrritantSet {
// group-2 warnings enabled by default
.set(
CompilerOptions.DeadCode
- |CompilerOptions.Tasks);
+ |CompilerOptions.Tasks
+ |CompilerOptions.UnclosedCloseable);
ALL.setAll();
HIDING
@@ -199,6 +202,9 @@ public class IrritantSet {
.set(CompilerOptions.RedundantSpecificationOfTypeArguments);
STATIC_METHOD
.set(CompilerOptions.MethodCanBePotentiallyStatic);
+ RESOURCE
+ .set(CompilerOptions.PotentiallyUnclosedCloseable)
+ .set(CompilerOptions.ExplicitlyClosedAutoCloseable);
String suppressRawWhenUnchecked = System.getProperty("suppressRawWhenUnchecked"); //$NON-NLS-1$
if (suppressRawWhenUnchecked != null && "true".equalsIgnoreCase(suppressRawWhenUnchecked)) { //$NON-NLS-1$
UNCHECKED.set(CompilerOptions.RawTypeReference);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index c2d4e4f8b..c0defeaa3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -1356,6 +1357,18 @@ public TypeVariableBinding getTypeVariable(char[] variableName) {
variable.resolve();
return variable;
}
+public boolean hasTypeBit(int bit) {
+ // ensure hierarchy is resolved, which will propagate bits down to us
+ boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType;
+ this.environment.mayTolerateMissingType = true;
+ try {
+ superclass();
+ superInterfaces();
+ } finally {
+ this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
+ }
+ return (this.typeBits & bit) != 0;
+}
private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper, char[][][] missingTypeNames) {
// ParameterSignature = Identifier ':' TypeSignature
// or Identifier ':' TypeSignature(optional) InterfaceBound(s)
@@ -1561,8 +1574,20 @@ public ReferenceBinding superclass() {
// finish resolving the type
this.superclass = (ReferenceBinding) resolveType(this.superclass, this.environment, true /* raw conversion */);
this.tagBits &= ~TagBits.HasUnresolvedSuperclass;
- if (this.superclass.problemId() == ProblemReasons.NotFound)
+ if (this.superclass.problemId() == ProblemReasons.NotFound) {
this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency
+ } else {
+ // make super-type resolving recursive for propagating typeBits downwards
+ boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType;
+ this.environment.mayTolerateMissingType = true; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=360164
+ try {
+ this.superclass.superclass();
+ this.superclass.superInterfaces();
+ } finally {
+ this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
+ }
+ }
+ this.typeBits |= this.superclass.typeBits;
return this.superclass;
}
//{ObjectTeams:
@@ -1589,8 +1614,20 @@ public ReferenceBinding[] superInterfaces() {
for (int i = this.superInterfaces.length; --i >= 0;) {
this.superInterfaces[i] = (ReferenceBinding) resolveType(this.superInterfaces[i], this.environment, true /* raw conversion */);
- if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound)
+ if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound) {
this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency
+ } else {
+ // make super-type resolving recursive for propagating typeBits downwards
+ boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType;
+ this.environment.mayTolerateMissingType = true; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=360164
+ try {
+ this.superInterfaces[i].superclass();
+ this.superInterfaces[i].superInterfaces();
+ } finally {
+ this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
+ }
+ }
+ this.typeBits |= this.superInterfaces[i].typeBits;
}
this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
return this.superInterfaces;
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 d5c5e9687..4a2041888 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
@@ -8,18 +8,24 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contributions for
+ * bug 349326 - [1.7] new warning for missing try-with-resources
+ * bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import java.util.ArrayList;
import java.util.LinkedList;
+import java.util.List;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.WrapperKind;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
@@ -31,7 +37,7 @@ import org.eclipse.objectteams.otdt.internal.core.compiler.util.TypeAnalyzer;
/**
* OTDT changes:
*
- * What: retreive all local types of this scope (identified by their ClassScope)
+ * What: retrieve all local types of this scope (identified by their ClassScope)
*
* What: Record referenced teams in getBinding(..)
*
@@ -1113,4 +1119,170 @@ public void resetEnclosingMethodStaticFlag() {
}
}
}
+
+private List trackingVariables; // can be null if no resources are tracked
+/** Used only during analyseCode and only for checking if a resource was closed in a finallyBlock. */
+public FlowInfo finallyInfo;
+/**
+ * Register a tracking variable and compute its id.
+ */
+public int registerTrackingVariable(FakedTrackingVariable fakedTrackingVariable) {
+ if (this.trackingVariables == null)
+ this.trackingVariables = new ArrayList(3);
+ this.trackingVariables.add(fakedTrackingVariable);
+ MethodScope outerMethodScope = outerMostMethodScope();
+ return outerMethodScope.analysisIndex + (outerMethodScope.trackVarCount++);
+
+}
+/** When are no longer interested in this tracking variable - remove it. */
+public void removeTrackingVar(FakedTrackingVariable trackingVariable) {
+ if (this.trackingVariables != null)
+ if (this.trackingVariables.remove(trackingVariable))
+ return;
+ if (this.parent instanceof BlockScope)
+ ((BlockScope)this.parent).removeTrackingVar(trackingVariable);
+}
+/**
+ * At the end of a block check the closing-status of all tracked closeables that are declared in this block.
+ * Also invoked when entering unreachable code.
+ */
+public void checkUnclosedCloseables(FlowInfo flowInfo, ASTNode location, BlockScope locationScope) {
+ if (this.trackingVariables == null) {
+ // at a method return we also consider enclosing scopes
+ if (location != null && this.parent instanceof BlockScope)
+ ((BlockScope) this.parent).checkUnclosedCloseables(flowInfo, location, locationScope);
+ return;
+ }
+ if (location != null && flowInfo.reachMode() != 0) return;
+ for (int i=0; i<this.trackingVariables.size(); i++) {
+ FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
+ if (location != null && trackingVar.originalBinding != null && flowInfo.isDefinitelyNull(trackingVar.originalBinding))
+ continue; // reporting against a specific location, resource is null at this flow, don't complain
+ int status = getNullStatusAggressively(trackingVar.binding, flowInfo);
+ // try to improve info if a close() inside finally was observed:
+ if (locationScope != null) // only check at method exit points
+ status = locationScope.mergeCloseStatus(status, trackingVar.binding, this);
+ if (status == FlowInfo.NULL) {
+ // definitely unclosed: highest priority
+ reportResourceLeak(trackingVar, location, status);
+ continue;
+ }
+ if (location == null) // at end of block and not definitely unclosed
+ {
+ // problems at specific locations: medium priority
+ if (trackingVar.reportRecordedErrors(this)) // ... report previously recorded errors
+ continue;
+ }
+ if (status == FlowInfo.POTENTIALLY_NULL) {
+ // potentially unclosed: lower priority
+ reportResourceLeak(trackingVar, location, status);
+ } else if (status == FlowInfo.NON_NULL) {
+ // properly closed but not managed by t-w-r: lowest priority
+ if (environment().globalOptions.complianceLevel >= ClassFileConstants.JDK1_7)
+ trackingVar.reportExplicitClosing(problemReporter());
+ }
+ }
+ if (location == null) {
+ // when leaving this block dispose off all tracking variables:
+ for (int i=0; i<this.localIndex; i++)
+ this.locals[i].closeTracker = null;
+ this.trackingVariables = null;
+ }
+}
+
+private int mergeCloseStatus(int status, LocalVariableBinding binding, BlockScope outerScope) {
+ // get the most suitable null status representing whether resource 'binding' has been closed
+ // start at this scope and potentially travel out until 'outerScope'
+ // at each scope consult any recorded 'finallyInfo'.
+ if (status != FlowInfo.NON_NULL) {
+ if (this.finallyInfo != null) {
+ int finallyStatus = this.finallyInfo.nullStatus(binding);
+ if (finallyStatus == FlowInfo.NON_NULL)
+ return finallyStatus;
+ if (finallyStatus != FlowInfo.NULL) // neither is NON_NULL, but not both are NULL => call it POTENTIALLY_NULL
+ status = FlowInfo.POTENTIALLY_NULL;
+ }
+ if (this != outerScope && this.parent instanceof BlockScope)
+ return ((BlockScope) this.parent).mergeCloseStatus(status, binding, outerScope);
+ }
+ return status;
+}
+
+private void reportResourceLeak(FakedTrackingVariable trackingVar, ASTNode location, int nullStatus) {
+ if (location != null)
+ trackingVar.recordErrorLocation(location, nullStatus);
+ else
+ trackingVar.reportError(problemReporter(), null, nullStatus);
+}
+
+/**
+ * If one branch of an if-else closes any AutoCloseable resource, and if the same
+ * resource is known to be null on the other branch mark it as closed, too,
+ * so that merging both branches indicates that the resource is always closed.
+ * Example:
+ * FileReader fr1 = null;
+ * try {\n" +
+ * fr1 = new FileReader(someFile);" +
+ * fr1.read(buf);\n" +
+ * } finally {\n" +
+ * if (fr1 != null)\n" +
+ * try {\n" +
+ * fr1.close();\n" +
+ * } catch (IOException e) {
+ * // do nothing
+ * }
+ * // after this if statement fr1 is definitely not leaked
+ * }
+ */
+public void correlateTrackingVarsIfElse(FlowInfo thenFlowInfo, FlowInfo elseFlowInfo) {
+ if (this.trackingVariables != null) {
+ for (int i=0; i<this.trackingVariables.size(); i++) {
+ FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
+ if ( thenFlowInfo.isDefinitelyNonNull(trackingVar.binding) // closed in then branch
+ && elseFlowInfo.isDefinitelyNull(trackingVar.originalBinding)) // null in else branch
+ {
+ elseFlowInfo.markAsDefinitelyNonNull(trackingVar.binding); // -> always closed
+ }
+ else if ( elseFlowInfo.isDefinitelyNonNull(trackingVar.binding) // closed in else branch
+ && thenFlowInfo.isDefinitelyNull(trackingVar.originalBinding)) // null in then branch
+ {
+ thenFlowInfo.markAsDefinitelyNonNull(trackingVar.binding); // -> always closed
+ }
+ }
+ }
+ if (this.parent instanceof BlockScope)
+ ((BlockScope) this.parent).correlateTrackingVarsIfElse(thenFlowInfo, elseFlowInfo);
+}
+
+/**
+ * Get the null status looking even into unreachable flows
+ * @param local
+ * @param flowInfo
+ * @return one of the constants FlowInfo.{NULL,POTENTIALLY_NULL,POTENTIALLY_NON_NULL,NON_NULL}.
+ */
+private int getNullStatusAggressively(LocalVariableBinding local, FlowInfo flowInfo) {
+ int reachMode = flowInfo.reachMode();
+ int status = 0;
+ try {
+ // unreachable flowInfo is too shy in reporting null-issues, temporarily forget reachability:
+ if (reachMode != FlowInfo.REACHABLE)
+ flowInfo.tagBits &= ~FlowInfo.UNREACHABLE;
+ status = flowInfo.nullStatus(local);
+ } finally {
+ // reset
+ flowInfo.tagBits |= reachMode;
+ }
+ // at this point some combinations are not useful so flatten to a single bit:
+ if ((status & FlowInfo.NULL) != 0) {
+ if ((status & (FlowInfo.NON_NULL | FlowInfo.POTENTIALLY_NON_NULL)) != 0)
+ return FlowInfo.POTENTIALLY_NULL; // null + doubt = pot null
+ return FlowInfo.NULL;
+ } else if ((status & FlowInfo.NON_NULL) != 0) {
+ if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
+ return FlowInfo.POTENTIALLY_NULL; // non-null + doubt = pot null
+ return FlowInfo.NON_NULL;
+ } else if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
+ return FlowInfo.POTENTIALLY_NULL;
+ return status;
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index 1a401d8b3..58e6dc532 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -11,6 +11,7 @@
* Bug 328281 - visibility leaks not detected when analyzing unused field in private class
* Bug 300576 - NPE Computing type hierarchy when compliance doesn't match libraries
* Bug 354536 - compiling package-info.java still depends on the order of compilation units
+ * Bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -1568,6 +1569,7 @@ public class ClassScope extends Scope {
} else {
// only want to reach here when no errors are reported
sourceType.superclass = superclass;
+ sourceType.typeBits |= superclass.typeBits;
return true;
}
}
@@ -2039,6 +2041,7 @@ public class ClassScope extends Scope {
noProblems &= superInterfaceRef.resolvedType.isValidBinding();
}
// only want to reach here when no errors are reported
+ sourceType.typeBits |= superInterface.typeBits;
interfaceBindings[count++] = superInterface;
}
// hold onto all correctly resolved superinterfaces
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
index b7e7794ee..6e54bfb0c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
@@ -7,7 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 185682 - Increment/decrement operators mark local variables as read
+ * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
+ * bug 185682 - Increment/decrement operators mark local variables as read
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -17,6 +19,7 @@ import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.impl.Constant;
@@ -47,6 +50,8 @@ public class LocalVariableBinding extends VariableBinding {
public int[] initializationPCs;
public int initializationCount = 0;
+ public FakedTrackingVariable closeTracker; // track closing of instances of type AutoCloseable, maybe null
+
// for synthetic local variables
// if declaration slot is not positionned, the variable will not be listed in attribute
// note that the name of a variable should be chosen so as not to conflict with user ones (usually starting with a space char is all needed)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index dfe33bc69..3550f2815 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -127,6 +127,7 @@ public class LookupEnvironment implements ProblemReasons, TypeConstants {
private ArrayList missingTypes;
Set typesBeingConnected;
public boolean isProcessingAnnotations = false;
+ public boolean mayTolerateMissingType = false;
final static int BUILD_FIELDS_AND_METHODS = 4;
final static int BUILD_TYPE_HIERARCHY = 1;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
index becddb09f..b37dcf7ad 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
@@ -8,6 +8,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -76,6 +77,9 @@ public class MethodScope extends BlockScope {
// inner-emulation
public SyntheticArgumentBinding[] extraSyntheticArguments;
+ // count number of tracking variables, see FakedTrackingVariable
+ int trackVarCount = 0;
+
public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) {
super(METHOD_SCOPE, parent);
this.locals = new LocalVariableBinding[5];
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
index 79979dfea..82dbcf6eb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
@@ -8,6 +8,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -672,6 +673,13 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
return this.type.hasMemberTypes();
}
+ public boolean hasTypeBit(int bit) {
+ TypeBinding erasure = erasure();
+ if (erasure instanceof ReferenceBinding)
+ return ((ReferenceBinding) erasure).hasTypeBit(bit);
+ return false;
+ }
+
/**
* @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#implementsMethod(MethodBinding)
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
index f97d9451d..1211cc1b8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
@@ -8,6 +8,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -65,6 +66,12 @@ public ReferenceBinding closestReferenceMatch() {
return this.closestMatch;
}
+public boolean hasTypeBit(int bit) {
+ if (this.closestMatch != null)
+ return this.closestMatch.hasTypeBit(bit);
+ return false;
+}
+
/* API
* Answer the problem id associated with the receiver.
* NoError if the receiver is a valid binding.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index a427a235c..b64379739 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -90,7 +91,11 @@ abstract public class ReferenceBinding extends AbstractOTReferenceBinding {
private SimpleLookupTable compatibleCache;
- public static final ReferenceBinding LUB_GENERIC = new ReferenceBinding() { /* used for lub computation */};
+ int typeBits; // additional bits characterizing this type
+
+ public static final ReferenceBinding LUB_GENERIC = new ReferenceBinding() { /* used for lub computation */
+ public boolean hasTypeBit(int bit) { return false; }
+ };
private static final Comparator FIELD_COMPARATOR = new Comparator() {
public int compare(Object o1, Object o2) {
@@ -570,6 +575,10 @@ public void computeId() {
case 'i' :
if (CharOperation.equals(packageName, TypeConstants.IO)) {
switch (typeName[0]) {
+ case 'C' :
+ if (CharOperation.equals(typeName, TypeConstants.JAVA_IO_CLOSEABLE[2]))
+ this.typeBits |= TypeIds.BitCloseable; // don't assign id, only typeBit (for analysis of resource leaks)
+ return;
case 'E' :
if (CharOperation.equals(typeName, TypeConstants.JAVA_IO_EXTERNALIZABLE[2]))
this.id = TypeIds.T_JavaIoExternalizable;
@@ -616,8 +625,10 @@ public void computeId() {
case 'A' :
switch(typeName.length) {
case 13 :
- if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_AUTOCLOSEABLE[2]))
+ if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_AUTOCLOSEABLE[2])) {
this.id = TypeIds.T_JavaLangAutoCloseable;
+ this.typeBits |= TypeIds.BitAutoCloseable;
+ }
return;
case 14:
if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ASSERTIONERROR[2]))
@@ -1026,6 +1037,8 @@ public FieldBinding getField(char[] fieldName, boolean needResolve) {
public char[] getFileName() {
return this.fileName;
}
+/** Answer an additional bit characterizing this type, like {@link TypeIds#BitAutoCloseable}. */
+abstract public boolean hasTypeBit(int bit);
public ReferenceBinding getMemberType(char[] typeName) {
ReferenceBinding[] memberTypes = memberTypes();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index 424f75176..e7b4226e4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -2719,6 +2719,40 @@ public abstract class Scope {
return new ProblemReferenceBinding(compoundName, null /* no closest match since search for pkg*/, ProblemReasons.NotFound);
}
+ /* Answer the package from the compoundName or null if it begins with a type.
+ * Intended to be used while resolving a package name only.
+ *
+ * Internal use only
+ */
+ public final Binding getOnlyPackage(char[][] compoundName) {
+ compilationUnitScope().recordQualifiedReference(compoundName);
+ Binding binding = getTypeOrPackage(compoundName[0], Binding.PACKAGE, true);
+ if (binding == null || !binding.isValidBinding()) {
+ char[][] qName = new char[][] { compoundName[0] };
+ return new ProblemReferenceBinding(qName, null /* no closest match since search for pkg*/, ProblemReasons.NotFound);
+ }
+ if (!(binding instanceof PackageBinding)) {
+ return null; // compoundName does not start with a package
+ }
+
+ int currentIndex = 1, length = compoundName.length;
+ PackageBinding packageBinding = (PackageBinding) binding;
+ while (currentIndex < length) {
+ binding = packageBinding.getPackage(compoundName[currentIndex++]);
+ if (binding == null) {
+ return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null /* no closest match since search for pkg*/, ProblemReasons.NotFound);
+ }
+ if (!binding.isValidBinding()) {
+ return new ProblemReferenceBinding(
+ CharOperation.subarray(compoundName, 0, currentIndex),
+ binding instanceof ReferenceBinding ? (ReferenceBinding)((ReferenceBinding)binding).closestMatch() : null,
+ binding.problemId());
+ }
+ packageBinding = (PackageBinding) binding;
+ }
+ return packageBinding;
+ }
+
/* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
* The name provided is a simple source name (e.g., "Object" , "Point", ...)
*/
@@ -3064,7 +3098,53 @@ public abstract class Scope {
}
}
}
-
+ // walk single static imports. A type found here will shadow types with same name in other CU's, or types coming
+ // from on-demand imports. JLS 7.5.3
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318401
+ if (imports != null) {
+ ReferenceBinding type = null;
+ nextImport : for (int i = 0, length = imports.length; i < length; i++) {
+ ImportBinding importBinding = imports[i];
+ if (importBinding.isStatic()) {
+ ReferenceBinding temp = null;
+ if (CharOperation.equals(importBinding.compoundName[importBinding.compoundName.length - 1], name)) {
+ Binding resolvedImport = importBinding.resolvedImport;
+ if (resolvedImport == null) continue nextImport;
+ if (resolvedImport instanceof MethodBinding || resolvedImport instanceof FieldBinding) {
+ // check to see if there are also member types with the same name
+ // must find the importRef's type again since the method/field can be from an inherited type
+ // see StaticImportTest#test084 for more clarity
+ char[][] importName = importBinding.reference.tokens;
+ TypeBinding referencedType = getType(importName, importName.length - 1);
+ if (referencedType != null && referencedType instanceof ReferenceBinding) {
+ temp = findMemberType(name, (ReferenceBinding) referencedType);
+ }
+ }
+ if (temp != null && temp.isStatic() && temp != type) {
+ if (temp.isValidBinding()) {
+ if (!temp.canBeSeenBy(unitScope.fPackage)) {
+ // Answer error binding - type is not visible
+ foundType = new ProblemReferenceBinding(new char[][]{name}, type, ProblemReasons.NotVisible);
+ } else {
+ ImportReference importReference = importBinding.reference;
+ if (importReference != null) {
+ importReference.bits |= ASTNode.Used;
+ }
+ type = temp;
+ }
+ } else if (foundType == null) {
+ foundType = temp;
+ }
+ }
+ }
+ }
+ }
+ if (type != null) {
+ if (typeOrPackageCache != null)
+ typeOrPackageCache.put(name, type);
+ return type;
+ }
+ }
// check if the name is in the current package, skip it if its a sub-package
PackageBinding currentPackage = unitScope.fPackage;
unitScope.recordReference(currentPackage.compoundName, name);
@@ -3409,7 +3489,7 @@ public abstract class Scope {
// test that the enclosingType is not part of the compilation unit
SourceTypeBinding[] topLevelTypes = ((CompilationUnitScope) unitScope).topLevelTypes;
for (int i = topLevelTypes.length; --i >= 0;)
- if (topLevelTypes[i] == enclosingType)
+ if (topLevelTypes[i] == enclosingType.original())
return true;
return false;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index e6b95e8df..f482f099a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.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 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -1621,6 +1623,11 @@ public SyntheticMethodBinding getSyntheticBridgeMethod(MethodBinding inheritedMe
return accessors[1];
}
+public boolean hasTypeBit(int bit) {
+ // source types initialize type bits during connectSuperclass/interfaces()
+ return (this.typeBits & bit) != 0;
+}
+
/**
* @see org.eclipse.jdt.internal.compiler.lookup.Binding#initializeDeprecatedAnnotationTagBits()
*/
@@ -1815,8 +1822,16 @@ public MethodBinding[] methods() {
int index = pLength;
// is erasure of signature of m2 same as signature of m1?
for (; --index >= 0;) {
- if (params1[index] != params2[index].erasure())
- break;
+ if (params1[index] != params2[index].erasure()) {
+ // If one of them is a raw type
+ if (params1[index] instanceof RawTypeBinding) {
+ if (params2[index].erasure() != ((RawTypeBinding)params1[index]).actualType()) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
if (params1[index] == params2[index]) {
TypeBinding type = params1[index].leafComponentType();
if (type instanceof SourceTypeBinding && type.typeVariables() != Binding.NO_TYPE_VARIABLES) {
@@ -1828,8 +1843,16 @@ public MethodBinding[] methods() {
if (index >= 0 && index < pLength) {
// is erasure of signature of m1 same as signature of m2?
for (index = pLength; --index >= 0;)
- if (params1[index].erasure() != params2[index])
- break;
+ if (params1[index].erasure() != params2[index]) {
+ // If one of them is a raw type
+ if (params2[index] instanceof RawTypeBinding) {
+ if (params1[index].erasure() != ((RawTypeBinding)params2[index]).actualType()) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
}
if (index >= 0) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
index 9a62cc02d..0bbef47eb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -123,6 +124,7 @@ public interface TypeConstants {
char[][] JAVA_LANG_ANNOTATION_ELEMENTTYPE = {JAVA, LANG, ANNOTATION, "ElementType".toCharArray()}; //$NON-NLS-1$
char[][] JAVA_LANG_REFLECT_FIELD = new char[][] {JAVA, LANG, REFLECT, "Field".toCharArray()}; //$NON-NLS-1$
char[][] JAVA_LANG_REFLECT_METHOD = new char[][] {JAVA, LANG, REFLECT, "Method".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_IO_CLOSEABLE = new char[][] { JAVA, IO, "Closeable".toCharArray()};//$NON-NLS-1$
char[][] JAVA_IO_OBJECTSTREAMEXCEPTION = new char[][] { JAVA, IO, "ObjectStreamException".toCharArray()};//$NON-NLS-1$
char[][] JAVA_IO_EXTERNALIZABLE = {JAVA, IO, "Externalizable".toCharArray()}; //$NON-NLS-1$
char[][] JAVA_IO_IOEXCEPTION = new char[][] { JAVA, IO, "IOException".toCharArray()};//$NON-NLS-1$
@@ -151,6 +153,7 @@ public interface TypeConstants {
"MethodHandle$PolymorphicSignature".toCharArray() //$NON-NLS-1$
};
char[][] JAVA_LANG_AUTOCLOSEABLE = {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$
+ char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$
// Constraints for generic type argument inference
int CONSTRAINT_EQUAL = 0; // Actual = Formal
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
index 8e3a647d5..115bf8339 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
@@ -7,6 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contributions for
+ * bug 349326 - [1.7] new warning for missing try-with-resources
+ * bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -182,4 +185,20 @@ public interface TypeIds {
final int Object2boolean = T_JavaLangObject + (T_boolean << 4);
final int BOXING = 0x200;
final int UNBOXING = 0x400;
+
+ /**
+ * Marks a type whose type bits have not yet been initialized.
+ * @see ReferenceBinding#hasTypeBit(int)
+ */
+ final int BitUninitialized = 0x8000000;
+ /**
+ * Marks all sub-types of java.lang.AutoCloseable.
+ * @see ReferenceBinding#hasTypeBit(int)
+ */
+ final int BitAutoCloseable = 1;
+ /**
+ * Marks all sub-types of java.io.Closeable.
+ * @see ReferenceBinding#hasTypeBit(int)
+ */
+ final int BitCloseable = 2;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
index 31433515b..29dc53f0b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,7 +7,10 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac
+ * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
+ * bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac
+ * bug 349326 - [1.7] new warning for missing try-with-resources
+ * bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
* Technical University Berlin - extended API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -53,6 +56,7 @@ public class TypeVariableBinding extends ReferenceBinding {
this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; // treat type var as public
this.tagBits |= TagBits.HasTypeVariable;
this.environment = environment;
+ this.typeBits = TypeIds.BitUninitialized;
}
/**
@@ -389,6 +393,20 @@ public class TypeVariableBinding extends ReferenceBinding {
return true;
}
+ public boolean hasTypeBit(int bit) {
+ if (this.typeBits == TypeIds.BitUninitialized) {
+ // initialize from bounds
+ this.typeBits = 0;
+ if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
+ this.typeBits |= this.superclass.typeBits;
+ if (this.superInterfaces != null)
+ for (int i = 0, l = this.superInterfaces.length; i < l; i++)
+ if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
+ this.typeBits |= this.superInterfaces[i].typeBits;
+ }
+ return (this.typeBits & bit) != 0;
+ }
+
/**
* Returns true if the type variable is directly bound to a given type
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
index f29aa59ab..1683193f1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -47,6 +48,10 @@ void addWrapper(TypeBinding wrapper, LookupEnvironment environment) {
public String debugName() {
return toString();
}
+public boolean hasTypeBit(int bit) {
+ // shouldn't happen since we are not called before analyseCode(), but play safe:
+ return false;
+}
//{ObjectTeams: changed to public (was default-vis)
public ReferenceBinding resolve(LookupEnvironment environment, boolean convertGenericToRawType) {
// SH}
@@ -58,7 +63,7 @@ public ReferenceBinding resolve(LookupEnvironment environment, boolean convertGe
}
if (targetType == null || targetType == this) { // could not resolve any better, error was already reported against it
// report the missing class file first - only if not resolving a previously missing type
- if ((this.tagBits & TagBits.HasMissingType) == 0) {
+ if ((this.tagBits & TagBits.HasMissingType) == 0 && !environment.mayTolerateMissingType) {
environment.problemReporter.isClassPathCorrect(
this.compoundName,
environment.unitBeingCompleted,
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
index a95cd85e0..a0fec342d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * Copyright (c) 2005, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * bug 349326 - [1.7] new warning for missing try-with-resources
+ * bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
* Technical University Berlin - extended API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -58,6 +61,7 @@ public class WildcardBinding extends ReferenceBinding {
if (bound instanceof UnresolvedReferenceBinding)
((UnresolvedReferenceBinding) bound).addWrapper(this, environment);
this.tagBits |= TagBits.HasUnresolvedTypeVariables; // cleared in resolve()
+ this.typeBits = TypeIds.BitUninitialized;
}
//{ObjectTeams: role wrapping?
@@ -434,6 +438,20 @@ public class WildcardBinding extends ReferenceBinding {
return this.genericType.hashCode();
}
+ public boolean hasTypeBit(int bit) {
+ if (this.typeBits == TypeIds.BitUninitialized) {
+ // initialize from upper bounds
+ this.typeBits = 0;
+ if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
+ this.typeBits |= this.superclass.typeBits;
+ if (this.superInterfaces != null)
+ for (int i = 0, l = this.superInterfaces.length; i < l; i++)
+ if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
+ this.typeBits |= this.superInterfaces[i].typeBits;
+ }
+ return (this.typeBits & bit) != 0;
+ }
+
void initialize(ReferenceBinding someGenericType, TypeBinding someBound, TypeBinding[] someOtherBounds) {
this.genericType = someGenericType;
this.bound = someBound;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 206854e7d..618e416f3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -10,8 +10,9 @@
* IBM Corporation - initial API and implementation
* Benjamin Muskalla - Contribution for bug 239066
* Stephan Herrmann - Contributions for
- * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
+ * bug 236385 -
* bug 338303 - Warning about Redundant assignment conflicts with definite assignment
+ * bug 349326 - [1.7] new warning for missing try-with-resources
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -59,6 +60,7 @@ import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FakedTrackingVariable;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
@@ -487,7 +489,16 @@ public static int getIrritant(int problemID) {
case IProblem.MethodCanBePotentiallyStatic:
return CompilerOptions.MethodCanBePotentiallyStatic;
-
+
+ case IProblem.UnclosedCloseable:
+ case IProblem.UnclosedCloseableAtExit:
+ return CompilerOptions.UnclosedCloseable;
+ case IProblem.PotentiallyUnclosedCloseable:
+ case IProblem.PotentiallyUnclosedCloseableAtExit:
+ return CompilerOptions.PotentiallyUnclosedCloseable;
+ case IProblem.ExplicitlyClosedAutoCloseable:
+ return CompilerOptions.ExplicitlyClosedAutoCloseable;
+
case IProblem.RedundantSpecificationOfTypeArguments:
return CompilerOptions.RedundantSpecificationOfTypeArguments;
//{ObjectTeams:
@@ -620,6 +631,7 @@ public static int getProblemCategory(int severity, int problemID) {
case CompilerOptions.ParameterAssignment :
case CompilerOptions.MethodCanBeStatic :
case CompilerOptions.MethodCanBePotentiallyStatic :
+ case CompilerOptions.ExplicitlyClosedAutoCloseable :
return CategorizedProblem.CAT_CODE_STYLE;
case CompilerOptions.MaskedCatchBlock :
@@ -641,6 +653,8 @@ public static int getProblemCategory(int severity, int problemID) {
case CompilerOptions.ShouldImplementHashcode :
case CompilerOptions.DeadCode :
case CompilerOptions.UnusedObjectAllocation :
+ case CompilerOptions.UnclosedCloseable :
+ case CompilerOptions.PotentiallyUnclosedCloseable :
return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM;
case CompilerOptions.OverriddenPackageDefaultMethod :
@@ -3153,12 +3167,21 @@ public void incorrectSwitchType(Expression expression, TypeBinding testType) {
expression.sourceStart,
expression.sourceEnd);
} else {
- this.handle(
- IProblem.IncorrectSwitchType,
- new String[] {new String(testType.readableName())},
- new String[] {new String(testType.shortReadableName())},
- expression.sourceStart,
- expression.sourceEnd);
+ if (this.options.sourceLevel < ClassFileConstants.JDK1_5 && testType.isEnum()) {
+ this.handle(
+ IProblem.SwitchOnEnumNotBelow15,
+ new String[] {new String(testType.readableName())},
+ new String[] {new String(testType.shortReadableName())},
+ expression.sourceStart,
+ expression.sourceEnd);
+ } else {
+ this.handle(
+ IProblem.IncorrectSwitchType,
+ new String[] {new String(testType.readableName())},
+ new String[] {new String(testType.shortReadableName())},
+ expression.sourceStart,
+ expression.sourceEnd);
+ }
}
} else {
this.handle(
@@ -8087,6 +8110,51 @@ public void unsafeRawInvocation(ASTNode location, MethodBinding rawMethod) {
location.sourceEnd);
}
}
+public void potentiallyUnclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) {
+ String[] args = { String.valueOf(trackVar.name) };
+ if (location == null) {
+ this.handle(
+ IProblem.PotentiallyUnclosedCloseable,
+ args,
+ args,
+ trackVar.sourceStart,
+ trackVar.sourceEnd);
+ } else {
+ this.handle(
+ IProblem.PotentiallyUnclosedCloseableAtExit,
+ args,
+ args,
+ location.sourceStart,
+ location.sourceEnd);
+ }
+}
+public void unclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) {
+ String[] args = { String.valueOf(trackVar.name) };
+ if (location == null) {
+ this.handle(
+ IProblem.UnclosedCloseable,
+ args,
+ args,
+ trackVar.sourceStart,
+ trackVar.sourceEnd);
+ } else {
+ this.handle(
+ IProblem.UnclosedCloseableAtExit,
+ args,
+ args,
+ location.sourceStart,
+ location.sourceEnd);
+ }
+}
+public void explicitlyClosedAutoCloseable(FakedTrackingVariable trackVar) {
+ String[] args = { String.valueOf(trackVar.name) };
+ this.handle(
+ IProblem.ExplicitlyClosedAutoCloseable,
+ args,
+ args,
+ trackVar.sourceStart,
+ trackVar.sourceEnd);
+}
public void unsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod, SourceTypeBinding type) {
if (this.options.sourceLevel < ClassFileConstants.JDK1_5) {
return;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index 787214954..1ae059427 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -8,7 +8,9 @@
# Contributors:
# IBM Corporation - initial API and implementation
# Benjamin Muskalla - Contribution for bug 239066
-# Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 185682 - Increment/decrement operators mark local variables as read
+# Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
+# bug 185682 - Increment/decrement operators mark local variables as read
+# bug 349326 - [1.7] new warning for missing try-with-resources
# Fraunhofer FIRST - extended API and implementation
# Technical University Berlin - extended API and implementation
###############################################################################
@@ -145,7 +147,7 @@
162 = Cannot return from within an initializer
163 = Initializer does not complete normally
164 = Expression must return a value
-165 = Unreachable catch block for {0}. Only more specific exceptions are thrown and handled by previous catch block(s).
+165 = Unreachable catch block for {0}. Only more specific exceptions are thrown and they are handled by previous catch block(s).
166 = The default case is already defined
167 = Unreachable catch block for {0}. This exception is never thrown from the try statement body
168 = Unhandled exception type {0}
@@ -289,7 +291,7 @@
343 = Illegal modifier for the interface field {0}.{1}; only public, static & final are permitted
344 = The field {0} can only set one of public / protected / private
345 = The field {0} can be either final or volatile, not both
-346 = The field {0} cannot be declared static; static fields can only be declared in static or top level types
+346 = The field {0} cannot be declared static in a non-static inner type, unless initialized with a constant expression
###[obsolete] 350 = {2} cannot be resolved (or is not a valid type) for the field {1}.{0}
###[obsolete] 351 = The type {2} is not visible for the field {1}.{0}
@@ -646,6 +648,12 @@
882 = Unhandled exception type {0} thrown by automatic close() invocation on {1}
883 = '<>' operator is not allowed for source level below 1.7
884 = Redundant specification of type arguments <{0}>
+885 = Potential resource leak: ''{0}'' may not be closed
+886 = Potential resource leak: ''{0}'' may not be closed at this location
+887 = Resource leak: ''{0}'' is never closed
+888 = Resource leak: ''{0}'' is not closed at this location
+889 = Resource ''{0}'' should be managed by try-with-resource
+890 = Cannot switch on an enum value for source level below 1.5. Only convertible int values are permitted
### ELABORATIONS
## Access restrictions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/RoleMigrationImplementor.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/RoleMigrationImplementor.java
index bfddb7c4c..6f87fe689 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/RoleMigrationImplementor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/RoleMigrationImplementor.java
@@ -21,13 +21,33 @@ import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccS
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ClassFile;
-import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
+import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
-import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
-import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
import org.eclipse.objectteams.otdt.internal.core.compiler.lifting.LiftingEnvironment;
@@ -252,7 +272,7 @@ public class RoleMigrationImplementor
return null;
}
@Override
- public void analyseCode(ClassScope classScope, InitializationFlowContext initializationContext, FlowInfo flowInfo) {
+ public void analyseCode(ClassScope classScope, FlowContext flowContext, FlowInfo flowInfo) {
// noop
}
};
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TeamMethodGenerator.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TeamMethodGenerator.java
index c9aea1c25..956cfc63e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TeamMethodGenerator.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TeamMethodGenerator.java
@@ -38,8 +38,8 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.MethodInfo;
import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
+import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
-import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
@@ -399,7 +399,7 @@ public class TeamMethodGenerator {
// nop
}
@Override
- public void analyseCode(ClassScope classScope, InitializationFlowContext initializationContext, FlowInfo flowInfo) {
+ public void analyseCode(ClassScope classScope, FlowContext flowContext, FlowInfo flowInfo) {
// nop
}
@Override
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
index baf8fc990..fe408d060 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -867,7 +867,7 @@ public class CompilationUnit extends ASTNode {
/**
* Enables the recording of changes to this compilation
- * unit and its descendents. The compilation unit must have
+ * unit and its descendants. The compilation unit must have
* been created by <code>ASTParser</code> and still be in
* its original state. Once recording is on,
* arbitrary changes to the subtree rooted at this compilation
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
index 9d64111df..08fa9a798 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
@@ -1578,7 +1578,7 @@ class DefaultBindingResolver extends BindingResolver {
org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(pkg);
if (node instanceof ImportReference) {
ImportReference importReference = (ImportReference) node;
- Binding binding = this.scope.getTypeOrPackage(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length));
+ Binding binding = this.scope.getOnlyPackage(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length));
if ((binding != null) && (binding.isValidBinding())) {
if (binding instanceof ReferenceBinding) {
// this only happens if a type name has the same name as its package
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
index aa2ea6603..c70d15293 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
@@ -890,10 +890,10 @@ public final class ASTRewriteAnalyzer extends ASTVisitor {
insertedPrefix = getLineDelimiter() + this.formatter.createIndentString(indent) + insertedPrefix.trim() + ' ';
}
doTextInsert(offset, insertedPrefix, editGroup);
- String lineInPrefix= getCurrentLine(prefix, prefix.length());
- if (prefix.length() != lineInPrefix.length()) {
+ int lineStart= getCurrentLineStart(prefix, prefix.length());
+ if (lineStart != 0) {
// prefix contains a new line: update the indent to the one used in the prefix
- indent= this.formatter.computeIndentUnits(lineInPrefix);
+ indent= this.formatter.computeIndentUnits(prefix.substring(lineStart));
}
doTextInsert(offset, replacingNode, indent, true, editGroup);
doTextInsert(offset, strings[1], editGroup);
@@ -1325,7 +1325,12 @@ public final class ASTRewriteAnalyzer extends ASTVisitor {
}
currPos= offset;
} else {
- String destIndentString= this.formatter.getIndentString(getCurrentLine(formatted, offset));
+ // If in the first line, there are cases (eg: catch clause) where the line will not be prefixed with
+ // proper indentation - see https://bugs.eclipse.org/bugs/show_bug.cgi?id=350285
+ int lineOffset = getCurrentLineStart(formatted, offset);
+ String destIndentString = (lineOffset == 0)
+ ? this.formatter.createIndentString(initialIndentLevel)
+ : this.formatter.getIndentString(formatted.substring(lineOffset, offset));
if (data instanceof CopyPlaceholderData) { // replace with a copy/move target
CopySourceInfo copySource= ((CopyPlaceholderData) data).copySource;
int srcIndentLevel= getIndent(copySource.getNode().getStartPosition());
@@ -1358,17 +1363,16 @@ public final class ASTRewriteAnalyzer extends ASTVisitor {
return offset < formatted.length() && !IndentManipulation.isLineDelimiterChar(formatted.charAt(offset));
}
- private String getCurrentLine(String str, int pos) {
+ private int getCurrentLineStart(String str, int pos) {
for (int i= pos - 1; i>= 0; i--) {
char ch= str.charAt(i);
if (IndentManipulation.isLineDelimiterChar(ch)) {
- return str.substring(i + 1, pos);
+ return i+1;
}
}
- return str.substring(0, pos);
+ return 0;
}
-
-
+
private void rewriteModifiers(ASTNode parent, StructuralPropertyDescriptor property, int offset) {
RewriteEvent event= getEvent(parent, property);
if (event == null || event.getChangeKind() != RewriteEvent.REPLACED) {
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
index d823ab6b6..d834f8271 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
@@ -112,7 +112,6 @@ import org.eclipse.jdt.internal.compiler.ast.WhileStatement;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
-import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
@@ -3845,8 +3844,7 @@ public class CodeFormatterVisitor extends ASTVisitor {
if (numberOfParens > 0) {
manageOpeningParenthesizedExpression(doubleLiteral, numberOfParens);
}
- Constant constant = doubleLiteral.constant;
- if (constant != null && constant.doubleValue() < 0) {
+ if (isNextToken(TerminalTokens.TokenNameMINUS)) {
this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);
}
this.scribe.printNextToken(TerminalTokens.TokenNameDoubleLiteral);
@@ -4070,8 +4068,7 @@ public class CodeFormatterVisitor extends ASTVisitor {
if (numberOfParens > 0) {
manageOpeningParenthesizedExpression(floatLiteral, numberOfParens);
}
- Constant constant = floatLiteral.constant;
- if (constant != null && floatLiteral.constant.floatValue() < 0) {
+ if (isNextToken(TerminalTokens.TokenNameMINUS)) {
this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);
}
this.scribe.printNextToken(TerminalTokens.TokenNameFloatingPointLiteral);
@@ -4384,8 +4381,7 @@ public class CodeFormatterVisitor extends ASTVisitor {
if (numberOfParens > 0) {
manageOpeningParenthesizedExpression(intLiteral, numberOfParens);
}
- Constant constant = intLiteral.constant;
- if (constant != null && constant.intValue() < 0) {
+ if (isNextToken(TerminalTokens.TokenNameMINUS)) {
this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);
}
this.scribe.printNextToken(TerminalTokens.TokenNameIntegerLiteral);
@@ -4435,8 +4431,7 @@ public class CodeFormatterVisitor extends ASTVisitor {
if (numberOfParens > 0) {
manageOpeningParenthesizedExpression(longLiteral, numberOfParens);
}
- Constant constant = longLiteral.constant;
- if (constant != null && constant.longValue() < 0) {
+ if (isNextToken(TerminalTokens.TokenNameMINUS)) {
this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);
}
this.scribe.printNextToken(TerminalTokens.TokenNameLongLiteral);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java
index dbc6e55c7..8d485abb8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -114,4 +114,13 @@ public interface IJavaModelMarker {
* @since 2.0
*/
String CLASSPATH_FILE_FORMAT = "classpathFileFormat"; //$NON-NLS-1$
+
+ /**
+ * Output overlapping another source attribute (value <code>"outputOverlappingSource"</code>).
+ * Used only on buildpath problem markers. The value of this attribute is
+ * either "true" or "false".
+ *
+ * @since 3.6.4
+ */
+ String OUTPUT_OVERLAPPING_SOURCE = "outputOverlappingSource"; //$NON-NLS-1$
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
index 4cc2f456b..a88db5e10 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
@@ -345,4 +345,11 @@ public interface IJavaModelStatusConstants {
* @since 3.7
*/
public static final int CANNOT_RETRIEVE_ATTACHED_JAVADOC_TIMEOUT = 1012;
+
+ /**
+ * <p>Status constant indicating that the default or specific output folder is overlapping
+ * with another source location. </p>
+ * @since 3.6.4
+ */
+ public static final int OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE = 1013;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
index a051e9122..4575100cf 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -618,11 +618,13 @@ public final class JavaConventions {
* <li> The project output location path cannot be null, must be absolute and located inside the project.
* <li> Specific output locations (specified on source entries) can be null, if not they must be located inside the project,
* <li> A project entry cannot refer to itself directly (that is, a project cannot prerequisite itself).
- * <li> Classpath entries or output locations cannot coincidate or be nested in each other, except for the following scenarii listed below:
- * <ul><li> A source folder can coincidate with its own output location, in which case this output can then contain library archives.
- * However, a specific output location cannot coincidate with any library or a distinct source folder than the one referring to it. </li>
+ * <li> Classpath entries or output locations cannot coincide or be nested in each other, except for the following scenarios listed below:
+ * <ul><li> A source folder can coincide with its own output location, in which case this output can then contain library archives.
+ * However, a specific output location cannot coincide with any library or a distinct source folder than the one referring to it.<br>
+ * Note: Since 3.8, this behavior can be overridden by configuring {@link JavaCore#CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE}
+ * </li>
* <li> A source/library folder can be nested in any source folder as long as the nested folder is excluded from the enclosing one. </li>
- * <li> An output location can be nested in a source folder, if the source folder coincidates with the project itself, or if the output
+ * <li> An output location can be nested in a source folder, if the source folder coincides with the project itself, or if the output
* location is excluded from the source folder.
* </ul>
* </ul>
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index fb5424b53..48d526532 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -84,6 +84,10 @@
* Benjamin Muskalla - added COMPILER_PB_MISSING_SYNCHRONIZED_ON_INHERITED_METHOD
* Stephan Herrmann - added COMPILER_PB_UNUSED_OBJECT_ALLOCATION
* Stephan Herrmann - added COMPILER_PB_SUPPRESS_OPTIONAL_ERRORS
+ * Stephan Herrmann - added the following constants:
+ * COMPILER_PB_UNCLOSED_CLOSEABLE,
+ * COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE
+ * COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE
*
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
@@ -1375,6 +1379,52 @@ public final class JavaCore extends Plugin {
*/
public static final String COMPILER_PB_POTENTIALLY_MISSING_STATIC_ON_METHOD = PLUGIN_ID + ".compiler.problem.reportMethodCanBePotentiallyStatic"; //$NON-NLS-1$
/**
+ * Compiler option ID: Reporting a resource that is not closed properly.
+ * <p>When enabled, the compiler will issue an error or a warning if
+ * a local variable holds a value of type <code>java.lang.AutoCloseable</code> (compliance>=1.7)
+ * or a value of type <code>java.io.Closeable</code> (compliance<=1.6) and if
+ * flow analysis shows that the method <code>close()</code> is not invoked locally on that value.
+ * <dl>
+ * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.reportUnclosedCloseable"</code></dd>
+ * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
+ * <dt>Default:</dt><dd><code>"warning"</code></dd>
+ * </dl>
+ * @since 3.8
+ * @category CompilerOptionID
+ */
+ public static final String COMPILER_PB_UNCLOSED_CLOSEABLE = PLUGIN_ID + ".compiler.problem.unclosedCloseable"; //$NON-NLS-1$
+ /**
+ * Compiler option ID: Reporting a resource that may not be closed properly.
+ * <p>When enabled, the compiler will issue an error or a warning if
+ * a local variable holds a value of type <code>java.lang.AutoCloseable</code> (compliance>=1.7)
+ * or a value of type <code>java.io.Closeable</code> (compliance<=1.6) and if
+ * flow analysis shows that the method <code>close()</code> is
+ * not invoked locally on that value for all execution paths.
+ * <dl>
+ * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.reportPotentiallyUnclosedCloseable"</code></dd>
+ * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
+ * <dt>Default:</dt><dd><code>"ignore"</code></dd>
+ * </dl>
+ * @since 3.8
+ * @category CompilerOptionID
+ */
+ public static final String COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE = PLUGIN_ID + ".compiler.problem.potentiallyUnclosedCloseable"; //$NON-NLS-1$
+ /**
+ * Compiler option ID: Reporting a resource that is not managed by try-with-resources.
+ * <p>When enabled, the compiler will issue an error or a warning if a local variable
+ * holds a value of type <code>java.lang.AutoCloseable</code>, and if the method
+ * <code>close()</code> is explicitly invoked on that resource, but the resource is
+ * not managed by a try-with-resources block.
+ * <dl>
+ * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.reportPotentiallyUnclosedCloseable"</code></dd>
+ * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
+ * <dt>Default:</dt><dd><code>"ignore"</code></dd>
+ * </dl>
+ * @since 3.8
+ * @category CompilerOptionID
+ */
+ public static final String COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE = PLUGIN_ID + ".compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$
+ /**
* Compiler option ID: Setting Source Compatibility Mode.
* <p>Specify whether which source level compatibility is used. From 1.4 on, <code>'assert'</code> is a keyword
* reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
@@ -1847,6 +1897,19 @@ public final class JavaCore extends Plugin {
*/
public static final String CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS = PLUGIN_ID + ".classpath.multipleOutputLocations"; //$NON-NLS-1$
/**
+ * Core option ID: Reporting an output location overlapping another source location.
+ * <p> Indicate the severity of the problem reported when a source entry's output location overlaps another
+ * source entry. </p>
+ *
+ * <dl>
+ * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource"</code></dd>
+ * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
+ * <dt>Default:</dt><dd><code>"error"</code></dd>
+ * </dl>
+ * @since 3.6.4
+ */
+ public static final String CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE = PLUGIN_ID + ".classpath.outputOverlappingAnotherSource"; //$NON-NLS-1$
+ /**
* Core option ID: Set the timeout value for retrieving the method's parameter names from javadoc.
* <p>Timeout in milliseconds to retrieve the method's parameter names from javadoc.
* <p>If the value is <code>0</code>, the parameter names are not fetched and the raw names are returned.
@@ -3714,6 +3777,7 @@ public final class JavaCore extends Plugin {
try {
if (JavaBuilder.DEBUG)
System.out.println("Touching " + project.getElementName()); //$NON-NLS-1$
+ new ClasspathValidation((JavaProject) project).validate(); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=287164
project.getProject().touch(progressMonitor2);
} catch (CoreException e) {
// could not touch this project: ignore
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java
index dd894ade6..c23af13ac 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -923,8 +923,9 @@ public class ByteCodeVisitorAdapter implements IBytecodeVisitor {
// default behavior is to do nothing
}
/**
- * @see IBytecodeVisitor#_invokeinterface(int, int, byte, IConstantPoolEntry)
+ * @see IBytecodeVisitor#_invokedynamic(int, int, IConstantPoolEntry, IConstantPoolEntry)
* @since 3.6
+ * @deprecated This has been replaced with {@link IBytecodeVisitor#_invokedynamic(int, int, IConstantPoolEntry)}
*/
public void _invokedynamic(
int pc,
@@ -934,6 +935,16 @@ public class ByteCodeVisitorAdapter implements IBytecodeVisitor {
// default behavior is to do nothing
}
/**
+ * @see IBytecodeVisitor#_invokedynamic(int, int, IConstantPoolEntry)
+ * @since 3.8
+ */
+ public void _invokedynamic(
+ int pc,
+ int index,
+ IConstantPoolEntry invokeDynamicEntry) {
+ // default behavior is to do nothing
+ }
+ /**
* @see IBytecodeVisitor#_invokeinterface(int, int, byte, IConstantPoolEntry)
*/
public void _invokeinterface(
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java
index e5dafa407..da838ec9c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -140,4 +140,10 @@ public interface IAttributeNamesConstants {
* @since 3.2
*/
char[] STACK_MAP = "StackMap".toCharArray(); //$NON-NLS-1$
+
+ /**
+ * "BootstrapMethods" attribute (added in cldc1.0).
+ * @since 3.8
+ */
+ char[] BOOTSTRAP_METHODS = "BootstrapMethods".toCharArray(); //$NON-NLS-1$
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBootstrapMethodsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBootstrapMethodsAttribute.java
new file mode 100644
index 000000000..d7bbd91a6
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBootstrapMethodsAttribute.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.util;
+
+/**
+ * Description of a bootstrap methods attribute as described in the JVM specifications.
+ *
+ * This interface may be implemented by clients.
+ *
+ * @since 3.8
+ */
+public interface IBootstrapMethodsAttribute extends IClassFileAttribute {
+
+ /**
+ * Answer back the number of bootstrap methods of this entry as specified in
+ * the JVM specifications.
+ *
+ * @return the number of bootstrap methods of this entry as specified in
+ * the JVM specifications
+ */
+ int getBootstrapMethodsLength();
+
+ /**
+ * Answer back the bootstrap methods table of this entry as specified in
+ * the JVM specifications. Answer an empty array if none.
+ *
+ * @return the bootstrap methods table of this entry as specified in
+ * the JVM specifications. Answer an empty array if none
+ */
+ IBootstrapMethodsEntry[] getBootstrapMethods();
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBootstrapMethodsEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBootstrapMethodsEntry.java
new file mode 100644
index 000000000..4078e85f9
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBootstrapMethodsEntry.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.util;
+
+/**
+ * Description of a bootstrap method table entry as specified in the JVM specifications.
+ *
+ * This interface may be implemented by clients.
+ *
+ * @since 3.8
+ */
+public interface IBootstrapMethodsEntry {
+
+ int getBootstrapMethodReference();
+ int[] getBootstrapArguments();
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBytecodeVisitor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBytecodeVisitor.java
index 52ccb168f..f36db8c38 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBytecodeVisitor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBytecodeVisitor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -168,12 +168,20 @@ public interface IBytecodeVisitor {
IConstantPoolEntry constantClass);
/**
* @since 3.6
+ * @deprecated This has been replaced with {@link #_invokedynamic(int, int, IConstantPoolEntry)}
*/
void _invokedynamic(
int pc,
int index,
IConstantPoolEntry nameEntry,
IConstantPoolEntry descriptorEntry);
+ /**
+ * @since 3.8
+ */
+ void _invokedynamic(
+ int pc,
+ int index,
+ IConstantPoolEntry invokeDynamic);
void _invokeinterface(
int pc,
int index,
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java
index 69526063b..9f57bb10f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -27,8 +27,7 @@ public interface IConstantPool {
int getConstantPoolCount();
/**
- * Answer back the type of the entry at the index @index
- * in the constant pool.
+ * Answer back the type of the entry at the given index in the constant pool.
*
* @param index the index of the entry in the constant pool
* @return the type of the entry at the index @index in the constant pool
@@ -36,11 +35,14 @@ public interface IConstantPool {
int getEntryKind(int index);
/**
- * Answer back the entry at the index @index
- * in the constant pool.
+ * Answer back the entry at the given index in the constant pool.
+ *
+ * <p>The return value can be an instance of {@link IConstantPoolEntry2} if the value returned
+ * by {@link #getEntryKind(int)} is either {@link IConstantPoolConstant#CONSTANT_MethodHandle},
+ * {@link IConstantPoolConstant#CONSTANT_MethodType} or {@link IConstantPoolConstant#CONSTANT_InvokeDynamic}.</p>
*
* @param index the index of the entry in the constant pool
- * @return the entry at the index @index in the constant pool
+ * @return the entry at the given index in the constant pool
*/
IConstantPoolEntry decodeEntry(int index);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java
index bc7cb54fb..ff6ed22c2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -29,6 +29,18 @@ public interface IConstantPoolConstant {
int CONSTANT_Double = 6;
int CONSTANT_NameAndType = 12;
int CONSTANT_Utf8 = 1;
+ /**
+ * @since 3.8
+ */
+ int CONSTANT_MethodHandle = 15;
+ /**
+ * @since 3.8
+ */
+ int CONSTANT_MethodType = 16;
+ /**
+ * @since 3.8
+ */
+ int CONSTANT_InvokeDynamic = 18;
int CONSTANT_Methodref_SIZE = 5;
int CONSTANT_Class_SIZE = 3;
@@ -41,5 +53,62 @@ public interface IConstantPoolConstant {
int CONSTANT_String_SIZE = 3;
int CONSTANT_Utf8_SIZE = 3;
int CONSTANT_NameAndType_SIZE = 5;
+ /**
+ * @since 3.8
+ */
+ int CONSTANT_MethodHandle_SIZE = 4;
+ /**
+ * @since 3.8
+ */
+ int CONSTANT_MethodType_SIZE = 3;
+ /**
+ * @since 3.8
+ */
+ int CONSTANT_InvokeDynamic_SIZE = 5;
+ /**
+ * The constant is described at 5.4.3.5 in the Java 7 VM specification (part 3).
+ * @since 3.8
+ */
+ int METHOD_TYPE_REF_GetField = 1;
+ /**
+ * The constant is described at 5.4.3.5 in the Java 7 VM specification (part 3).
+ * @since 3.8
+ */
+ int METHOD_TYPE_REF_GetStatic = 2;
+ /**
+ * The constant is described at 5.4.3.5 in the Java 7 VM specification (part 3).
+ * @since 3.8
+ */
+ int METHOD_TYPE_REF_PutField = 3;
+ /**
+ * The constant is described at 5.4.3.5 in the Java 7 VM specification (part 3).
+ * @since 3.8
+ */
+ int METHOD_TYPE_REF_PutStatic = 4;
+ /**
+ * The constant is described at 5.4.3.5 in the Java 7 VM specification (part 3).
+ * @since 3.8
+ */
+ int METHOD_TYPE_REF_InvokeVirtual = 5;
+ /**
+ * The constant is described at 5.4.3.5 in the Java 7 VM specification (part 3).
+ * @since 3.8
+ */
+ int METHOD_TYPE_REF_InvokeStatic = 6;
+ /**
+ * The constant is described at 5.4.3.5 in the Java 7 VM specification (part 3).
+ * @since 3.8
+ */
+ int METHOD_TYPE_REF_InvokeSpecial = 7;
+ /**
+ * The constant is described at 5.4.3.5 in the Java 7 VM specification (part 3).
+ * @since 3.8
+ */
+ int METHOD_TYPE_REF_NewInvokeSpecial = 8;
+ /**
+ * The constant is described at 5.4.3.5 in the Java 7 VM specification (part 3).
+ * @since 3.8
+ */
+ int METHOD_TYPE_REF_InvokeInterface = 9;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry.java
index 487ad82e4..c75bd40be 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -32,6 +32,7 @@ public interface IConstantPoolEntry {
* The value is unspecified otherwise.
*
* @return the name index for a CONSTANT_Class type entry
+ * @see IConstantPoolConstant#CONSTANT_Class
*/
int getClassInfoNameIndex();
@@ -42,16 +43,25 @@ public interface IConstantPoolEntry {
*
* @return the class index for a CONSTANT_Fieldref,
* CONSTANT_Methodref, CONSTANT_InterfaceMethodref type entry
+ * @see IConstantPoolConstant#CONSTANT_Fieldref
+ * @see IConstantPoolConstant#CONSTANT_Methodref
+ * @see IConstantPoolConstant#CONSTANT_InterfaceMethodref
*/
int getClassIndex();
/**
* Returns the nameAndType index for a CONSTANT_Fieldref,
- * CONSTANT_Methodref, CONSTANT_InterfaceMethodref type entry.
+ * CONSTANT_Methodref, CONSTANT_InterfaceMethodref,
+ * CONSTANT_InvokeDynamic type entry.
* The value is unspecified otherwise.
*
* @return the nameAndType index for a CONSTANT_Fieldref,
- * CONSTANT_Methodref, CONSTANT_InterfaceMethodref type entry
+ * CONSTANT_Methodref, CONSTANT_InterfaceMethodref,
+ * CONSTANT_InvokeDynamic type entry
+ * @see IConstantPoolConstant#CONSTANT_Fieldref
+ * @see IConstantPoolConstant#CONSTANT_Methodref
+ * @see IConstantPoolConstant#CONSTANT_InterfaceMethodref
+ * @see IConstantPoolConstant#CONSTANT_InvokeDynamic
*/
int getNameAndTypeIndex();
@@ -60,6 +70,7 @@ public interface IConstantPoolEntry {
* The value is unspecified otherwise.
*
* @return the string index for a CONSTANT_String type entry
+ * @see IConstantPoolConstant#CONSTANT_String
*/
int getStringIndex();
@@ -68,6 +79,7 @@ public interface IConstantPoolEntry {
* Returns null otherwise.
*
* @return the string value for a CONSTANT_String type entry
+ * @see IConstantPoolConstant#CONSTANT_String
*/
String getStringValue();
@@ -76,6 +88,7 @@ public interface IConstantPoolEntry {
* The value is unspecified otherwise.
*
* @return the integer value for a CONSTANT_Integer type entry
+ * @see IConstantPoolConstant#CONSTANT_Integer
*/
int getIntegerValue();
@@ -84,6 +97,7 @@ public interface IConstantPoolEntry {
* The value is unspecified otherwise.
*
* @return the float value for a CONSTANT_Float type entry
+ * @see IConstantPoolConstant#CONSTANT_Float
*/
float getFloatValue();
@@ -92,6 +106,7 @@ public interface IConstantPoolEntry {
* The value is unspecified otherwise.
*
* @return the double value for a CONSTANT_Double type entry
+ * @see IConstantPoolConstant#CONSTANT_Double
*/
double getDoubleValue();
@@ -100,6 +115,7 @@ public interface IConstantPoolEntry {
* The value is unspecified otherwise.
*
* @return the long value for a CONSTANT_Long type entry
+ * @see IConstantPoolConstant#CONSTANT_Long
*/
long getLongValue();
@@ -108,6 +124,7 @@ public interface IConstantPoolEntry {
* The value is unspecified otherwise.
*
* @return the descriptor index for a CONSTANT_NameAndType type entry
+ * @see IConstantPoolConstant#CONSTANT_NameAndType
*/
int getNameAndTypeInfoDescriptorIndex();
@@ -116,6 +133,7 @@ public interface IConstantPoolEntry {
* The value is unspecified otherwise.
*
* @return the name index for a CONSTANT_NameAndType type entry
+ * @see IConstantPoolConstant#CONSTANT_NameAndType
*/
int getNameAndTypeInfoNameIndex();
@@ -124,6 +142,7 @@ public interface IConstantPoolEntry {
* Returns null otherwise.
*
* @return the class name for a CONSTANT_Class type entry
+ * @see IConstantPoolConstant#CONSTANT_Class
*/
char[] getClassInfoName();
@@ -134,6 +153,9 @@ public interface IConstantPoolEntry {
*
* @return the class name for a CONSTANT_Fieldref,
* CONSTANT_Methodref, CONSTANT_InterfaceMethodref type entry
+ * @see IConstantPoolConstant#CONSTANT_Fieldref
+ * @see IConstantPoolConstant#CONSTANT_Methodref
+ * @see IConstantPoolConstant#CONSTANT_InterfaceMethodref
*/
char[] getClassName();
@@ -142,16 +164,20 @@ public interface IConstantPoolEntry {
* Returns null otherwise.
*
* @return the field name for a CONSTANT_Fieldref type entry
+ * @see IConstantPoolConstant#CONSTANT_Fieldref
*/
char[] getFieldName();
/**
- * Returns the field name for a CONSTANT_Methodref or CONSTANT_InterfaceMethodred
- * type entry.
+ * Returns the field name for a CONSTANT_Methodref, CONSTANT_InterfaceMethodref
+ * or CONSTANT_InvokeDynamic type entry.
* Returns null otherwise.
*
- * @return the field name for a CONSTANT_Methodref or CONSTANT_InterfaceMethodred
- * type entry
+ * @return the method name for a CONSTANT_Methodref, CONSTANT_InterfaceMethodref
+ * or CONSTANT_InvokeDynamic type entry
+ * @see IConstantPoolConstant#CONSTANT_Methodref
+ * @see IConstantPoolConstant#CONSTANT_InterfaceMethodref
+ * @see IConstantPoolConstant#CONSTANT_InvokeDynamic
*/
char[] getMethodName();
@@ -162,18 +188,27 @@ public interface IConstantPoolEntry {
*
* @return the field descriptor value for a CONSTANT_Fieldref type entry. This value
* is set only when decoding the CONSTANT_Fieldref entry
+ * @see IConstantPoolConstant#CONSTANT_Fieldref
*/
char[] getFieldDescriptor();
/**
* Returns the method descriptor value for a CONSTANT_Methodref or
* CONSTANT_InterfaceMethodref type entry. This value is set only when decoding the
- * CONSTANT_Methodref or CONSTANT_InterfaceMethodref entry.
+ * CONSTANT_Methodref, CONSTANT_InterfaceMethodref, CONSTANT_MethodType
+ * or CONSTANT_InvokeDynamic entry.
+ *
* Returns null otherwise.
*
- * @return the method descriptor value for a CONSTANT_Methodref or
+ * @return the method descriptor value for a CONSTANT_Methodref,
* CONSTANT_InterfaceMethodref type entry. This value is set only when decoding the
- * CONSTANT_Methodref or CONSTANT_InterfaceMethodref entry
+ * CONSTANT_Methodref, CONSTANT_InterfaceMethodref, CONSTANT_MethodType
+ * or CONSTANT_InvokeDynamic entry
+ *
+ * @see IConstantPoolConstant#CONSTANT_Methodref
+ * @see IConstantPoolConstant#CONSTANT_InterfaceMethodref
+ * @see IConstantPoolConstant#CONSTANT_MethodType
+ * @see IConstantPoolConstant#CONSTANT_InvokeDynamic
*/
char[] getMethodDescriptor();
@@ -184,6 +219,7 @@ public interface IConstantPoolEntry {
*
* @return the utf8 value for a CONSTANT_Utf8 type entry. This value is set only when
* decoding a UTF8 entry
+ * @see IConstantPoolConstant#CONSTANT_Utf8
*/
char[] getUtf8Value();
@@ -194,6 +230,7 @@ public interface IConstantPoolEntry {
*
* @return the utf8 length for a CONSTANT_Utf8 type entry. This value is set only when
* decoding a UTF8 entry
+ * @see IConstantPoolConstant#CONSTANT_Utf8
*/
int getUtf8Length();
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry2.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry2.java
new file mode 100644
index 000000000..3b4984bcd
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolEntry2.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.util;
+
+/**
+ * Description of the new constant pool entry as described in the JVM specifications
+ * added for Java 7 support.
+ * Its contents is initialized according to its kind.
+ *
+ * This interface may be implemented by clients.
+ *
+ * @since 3.8
+ */
+public interface IConstantPoolEntry2 extends IConstantPoolEntry {
+ /**
+ * Returns the descriptor index. This value is set only when decoding a MethodType entry.
+ * The value is unspecified otherwise. The corresponding UTF8 value can be retrieved by using
+ * {@link #getMethodDescriptor()}.
+ *
+ * @return the descriptor index. This value is set only when decoding a MethodType entry.
+ * @see IConstantPoolConstant#CONSTANT_MethodType
+ */
+ int getDescriptorIndex();
+
+ /**
+ * Returns the reference kind. This value is set only when decoding a MethodHandle entry.
+ * The value is unspecified otherwise.
+ *
+ * @return the reference kind. This value is set only when decoding a MethodHandle entry.
+ * @see IConstantPoolConstant#CONSTANT_MethodHandle
+ */
+ int getReferenceKind();
+
+ /**
+ * Returns the reference index. This value is set only when decoding a MethodHandle entry.
+ * The value is unspecified otherwise.
+ *
+ * @return the reference kind. This value is set only when decoding a MethodHandle entry.
+ * @see IConstantPoolConstant#CONSTANT_MethodHandle
+ */
+ int getReferenceIndex();
+
+ /**
+ * Returns the bootstrap method attribute index. This value is set only when decoding a InvokeDynamic entry.
+ * The value is unspecified otherwise.
+ *
+ * @return the reference kind. This value is set only when decoding a MethodHandle entry.
+ * @see IConstantPoolConstant#CONSTANT_InvokeDynamic
+ */
+ int getBootstrapMethodAttributeIndex();
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
index fbd0b539b..d1bbbb38a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,7 +8,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann <stephan@cs.tu-berlin.de> - TypeConverters don't set enclosingType - https://bugs.eclipse.org/bugs/show_bug.cgi?id=320841
+ * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
+ * Bug 320841 - TypeConverters don't set enclosingType
+ * Bug 353474 - type converters should include more annotations
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
@@ -32,6 +34,7 @@ import org.eclipse.jdt.core.IAnnotatable;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
@@ -405,6 +408,7 @@ public class SourceTypeConverter extends TypeConverter {
char[][] argumentNames = methodInfo.getArgumentNames();
int argumentCount = argumentTypeSignatures == null ? 0 : argumentTypeSignatures.length;
if (argumentCount > 0) {
+ ILocalVariable[] parameters = methodHandle.getParameters();
long position = ((long) start << 32) + end;
method.arguments = new Argument[argumentCount];
for (int i = 0; i < argumentCount; i++) {
@@ -426,6 +430,11 @@ public class SourceTypeConverter extends TypeConverter {
typeReference,
ClassFileConstants.AccDefault);
// do not care whether was final or not
+ // convert 1.5 specific constructs only if compliance is 1.5 or above
+ if (this.has1_5Compliance) {
+ /* convert annotations */
+ method.arguments[i].annotations = convertAnnotations(parameters[i]);
+ }
}
}
//{ObjectTeams: enhance signature for callin method:
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
index d8086ffc9..5656323e4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Terry Parker <tparker@google.com> - DeltaProcessor misses state changes in archive files, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=357425
*******************************************************************************/
package org.eclipse.jdt.internal.core;
@@ -1776,6 +1777,7 @@ public class ClasspathEntry implements IClasspathEntry {
// perform one separate iteration so as to not take precedence over previously checked scenarii (in particular should
// diagnose nesting source folder issue before this one, for example, [src]"Project/", [src]"Project/source/" and output="Project/" should
// first complain about missing exclusion pattern
+ IJavaModelStatus cachedStatus = null;
for (int i = 0 ; i < length; i++) {
IClasspathEntry entry = classpath[i];
if (entry == null) continue;
@@ -1788,30 +1790,53 @@ public class ClasspathEntry implements IClasspathEntry {
if (kind == IClasspathEntry.CPE_SOURCE) {
IPath output = entry.getOutputLocation();
- if (output == null) continue; // 36465 - for 2.0 backward compatibility, only check specific output locations (the default can still coincidate)
- // if (output == null) output = projectOutputLocation; // if no specific output, still need to check using default output (this line would check default output)
+ if (output == null) output = projectOutputLocation; // if no specific output, still need to check using default output (this line would check default output)
for (int j = 0; j < length; j++) {
IClasspathEntry otherEntry = classpath[j];
if (otherEntry == entry) continue;
- // Build some common strings for status message
- boolean opStartsWithProject = projectName.equals(otherEntry.getPath().segment(0));
- String otherPathMsg = opStartsWithProject ? otherEntry.getPath().removeFirstSegments(1).toString() : otherEntry.getPath().makeRelative().toString();
-
switch (otherEntry.getEntryKind()) {
case IClasspathEntry.CPE_SOURCE :
- if (otherEntry.getPath().equals(output)) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotUseDistinctSourceFolderAsOutput, new String[] {entryPathMsg, otherPathMsg, projectName}));
+ // Bug 287164 : Report errors of overlapping output locations only if the user sets the corresponding preference.
+ // The check is required for backward compatibility with bug-fix 36465.
+ String option = javaProject.getOption(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, true);
+ if (otherEntry.getPath().equals(output)
+ && !JavaCore.IGNORE.equals(option)) {
+ boolean opStartsWithProject = projectName.equals(otherEntry.getPath().segment(0));
+ String otherPathMsg = opStartsWithProject ? otherEntry.getPath().removeFirstSegments(1).toString() : otherEntry.getPath().makeRelative().toString();
+ if (JavaCore.ERROR.equals(option)) {
+ return new JavaModelStatus(IStatus.ERROR, IJavaModelStatusConstants.OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE,
+ Messages.bind(Messages.classpath_cannotUseDistinctSourceFolderAsOutput, new String[] {
+ entryPathMsg, otherPathMsg, projectName }));
+ }
+ if (cachedStatus == null) {
+ // Note that the isOK() is being overridden to return true. This is an exceptional scenario
+ cachedStatus = new JavaModelStatus(IStatus.OK, IJavaModelStatusConstants.OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE,
+ Messages.bind(Messages.classpath_cannotUseDistinctSourceFolderAsOutput, new String[] {
+ entryPathMsg, otherPathMsg, projectName })){
+ public boolean isOK() {
+ return true;
+ }
+ };
+ }
}
break;
case IClasspathEntry.CPE_LIBRARY :
- if (otherEntry.getPath().equals(output)) {
+ if (output != projectOutputLocation && otherEntry.getPath().equals(output)) {
+ boolean opStartsWithProject = projectName.equals(otherEntry.getPath().segment(0));
+ String otherPathMsg = opStartsWithProject ? otherEntry.getPath().removeFirstSegments(1).toString() : otherEntry.getPath().makeRelative().toString();
return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotUseLibraryAsOutput, new String[] {entryPathMsg, otherPathMsg, projectName}));
}
}
}
}
}
+
+ // NOTE: The above code that checks for IJavaModelStatusConstants.OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, can be configured to return
+ // a WARNING status and hence should be at the end of this validation method. Any other code that might return a more severe ERROR should be
+ // inserted before the mentioned code.
+ if (cachedStatus != null) return cachedStatus;
+
return JavaModelStatus.VERIFIED_OK;
}
@@ -1827,6 +1852,9 @@ public class ClasspathEntry implements IClasspathEntry {
* @return a java model status describing the problem related to this classpath entry if any, a status object with code <code>IStatus.OK</code> if the entry is fine
*/
public static IJavaModelStatus validateClasspathEntry(IJavaProject project, IClasspathEntry entry, boolean checkSourceAttachment, boolean referredByContainer){
+ if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
+ JavaModelManager.getJavaModelManager().removeFromInvalidArchiveCache(entry.getPath());
+ }
IJavaModelStatus status = validateClasspathEntry(project, entry, null, checkSourceAttachment, referredByContainer);
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=171136 and https://bugs.eclipse.org/bugs/show_bug.cgi?id=300136
// Ignore class path errors from optional entries.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathValidation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathValidation.java
index ea310a3c2..345535ac1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathValidation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathValidation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,6 +12,7 @@ package org.eclipse.jdt.internal.core;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaModelStatus;
import org.eclipse.jdt.core.JavaModelException;
@@ -37,7 +38,7 @@ public class ClasspathValidation {
// project doesn't exist
IProject resource = this.project.getProject();
if (resource.isAccessible()) {
- this.project.flushClasspathProblemMarkers(true/*flush cycle markers*/, true/*flush classpath format markers*/);
+ this.project.flushClasspathProblemMarkers(true/*flush cycle markers*/, true/*flush classpath format markers*/, true /*flush overlapping output markers*/);
// remove problems and tasks created by the builder
JavaBuilder.removeProblemsAndTasksFor(resource);
@@ -56,12 +57,15 @@ public class ClasspathValidation {
}
// update classpath format problems
- this.project.flushClasspathProblemMarkers(false/*cycle*/, true/*format*/);
+ this.project.flushClasspathProblemMarkers(false/*cycle*/, true/*format*/, false/*overlapping*/);
if (!status.isOK())
this.project.createClasspathProblemMarker(status);
+ // update overlapping output problem markers
+ this.project.flushClasspathProblemMarkers(false/*cycle*/, false/*format*/, true/*overlapping*/);
+
// update resolved classpath problems
- this.project.flushClasspathProblemMarkers(false/*cycle*/, false/*format*/);
+ this.project.flushClasspathProblemMarkers(false/*cycle*/, false/*format*/, false/*overlapping*/);
if (rawClasspath != JavaProject.INVALID_CLASSPATH && outputLocation != null) {
for (int i = 0; i < rawClasspath.length; i++) {
@@ -71,7 +75,7 @@ public class ClasspathValidation {
}
}
status = ClasspathEntry.validateClasspath(this.project, rawClasspath, outputLocation);
- if (!status.isOK())
+ if (status.getCode() != IStatus.OK)
this.project.createClasspathProblemMarker(status);
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
index f2b617350..4a1d8ba87 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -100,8 +100,9 @@ public class CompilationUnitProblemFinder extends Compiler {
*/
public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
// ensure to jump back to toplevel type for first one (could be a member)
-// while (sourceTypes[0].getEnclosingType() != null)
-// sourceTypes[0] = sourceTypes[0].getEnclosingType();
+ while (sourceTypes[0].getEnclosingType() != null) {
+ sourceTypes[0] = sourceTypes[0].getEnclosingType();
+ }
CompilationResult result =
new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.options.maxProblemsPerUnit);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
index f7a0c1cb8..126fcc918 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Terry Parker <tparker@google.com> - DeltaProcessor exhibits O(N^2) behavior, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=354332
+ * Terry Parker <tparker@google.com> - DeltaProcessor misses state changes in archive files, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=357425
*******************************************************************************/
package org.eclipse.jdt.internal.core;
@@ -954,7 +955,7 @@ public class DeltaProcessor {
// project does not exist -> ignore
continue;
}
- boolean hasChainedJar = false;
+ boolean deltaContainsModifiedJar = false;
for (int j = 0; j < entries.length; j++){
if (entries[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
IPath entryPath = entries[j].getPath();
@@ -1024,7 +1025,7 @@ public class DeltaProcessor {
System.out.println("- External JAR ADDED, affecting root: "+root.getElementName()); //$NON-NLS-1$
}
elementAdded(root, null, null);
- hasChainedJar |= !this.manager.isNonChainingJar(entryPath);
+ deltaContainsModifiedJar = true;
this.state.addClasspathValidation(javaProject); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185733
hasDelta = true;
} else if (status == EXTERNAL_JAR_CHANGED) {
@@ -1033,7 +1034,7 @@ public class DeltaProcessor {
System.out.println("- External JAR CHANGED, affecting root: "+root.getElementName()); //$NON-NLS-1$
}
contentChanged(root);
- hasChainedJar |= !this.manager.isNonChainingJar(entryPath);
+ deltaContainsModifiedJar = true;
hasDelta = true;
} else if (status == EXTERNAL_JAR_REMOVED) {
PackageFragmentRoot root = (PackageFragmentRoot) javaProject.getPackageFragmentRoot(entryPath.toString());
@@ -1041,7 +1042,7 @@ public class DeltaProcessor {
System.out.println("- External JAR REMOVED, affecting root: "+root.getElementName()); //$NON-NLS-1$
}
elementRemoved(root, null, null);
- hasChainedJar |= !this.manager.isNonChainingJar(entryPath);
+ deltaContainsModifiedJar = true;
this.state.addClasspathValidation(javaProject); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185733
hasDelta = true;
}
@@ -1049,7 +1050,7 @@ public class DeltaProcessor {
}
}
- if (hasChainedJar) {
+ if (deltaContainsModifiedJar) {
javaProject.resetResolvedClasspath();
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
index 532ed94d7..91c6ddeca 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
@@ -58,6 +58,7 @@ public class JavaCorePreferenceInitializer extends AbstractPreferenceInitializer
defaultOptionsMap.put(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, JavaCore.IGNORE);
defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, JavaCore.ENABLED);
defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, JavaCore.ENABLED);
+ defaultOptionsMap.put(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, JavaCore.ERROR);
// encoding setting comes from resource plug-in
optionNames.add(JavaCore.CORE_ENCODING);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index 4127a2236..d9048ce78 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -11,6 +11,7 @@
* before its contents
* (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=102422)
* Stephan Herrmann - Contribution for Bug 346010 - [model] strange initialization dependency in OptionTests
+ * Terry Parker <tparker@google.com> - DeltaProcessor misses state changes in archive files, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=357425
* Technical University Berlin - extended API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.core;
@@ -1487,7 +1488,8 @@ public class JavaModelManager implements ISaveParticipant, IContentTypeChangeLis
propertyName.equals(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS) ||
propertyName.equals(JavaCore.CORE_INCOMPLETE_CLASSPATH) ||
propertyName.equals(JavaCore.CORE_CIRCULAR_CLASSPATH) ||
- propertyName.equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL)) {
+ propertyName.equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL) ||
+ propertyName.equals(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE)) {
JavaModelManager manager = JavaModelManager.getJavaModelManager();
IJavaModel model = manager.getJavaModel();
IJavaProject[] projects;
@@ -2254,7 +2256,8 @@ public class JavaModelManager implements ISaveParticipant, IContentTypeChangeLis
defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_ORDER, JavaCore.IGNORE);
defaultOptionsMap.put(JavaCore.CORE_INCOMPLETE_CLASSPATH, JavaCore.ERROR);
defaultOptionsMap.put(JavaCore.CORE_CIRCULAR_CLASSPATH, JavaCore.ERROR);
- defaultOptionsMap.put(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, JavaCore.IGNORE);
+ defaultOptionsMap.put(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, JavaCore.IGNORE);
+ defaultOptionsMap.put(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, JavaCore.ERROR);
defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, JavaCore.ENABLED);
defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, JavaCore.ENABLED);
@@ -3092,6 +3095,12 @@ public class JavaModelManager implements ISaveParticipant, IContentTypeChangeLis
return this.invalidArchives != null && this.invalidArchives.contains(path);
}
+ public void removeFromInvalidArchiveCache(IPath path) {
+ if (this.invalidArchives != null) {
+ this.invalidArchives.remove(path);
+ }
+ }
+
public void setClasspathBeingResolved(IJavaProject project, boolean classpathIsResolved) {
if (classpathIsResolved) {
getClasspathBeingResolved().add(project);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
index 5de8f6480..5fd9dce56 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
@@ -437,7 +437,7 @@ public class JavaProject
new JavaModelStatus(IJavaModelStatusConstants.CLASSPATH_CYCLE, project, cycleString));
}
} else {
- project.flushClasspathProblemMarkers(true, false);
+ project.flushClasspathProblemMarkers(true, false, false);
}
}
}
@@ -807,7 +807,7 @@ public class JavaProject
IMarker marker = null;
int severity;
String[] arguments = CharOperation.NO_STRINGS;
- boolean isCycleProblem = false, isClasspathFileFormatProblem = false;
+ boolean isCycleProblem = false, isClasspathFileFormatProblem = false, isOutputOverlapping = false;
switch (status.getCode()) {
case IJavaModelStatusConstants.CLASSPATH_CYCLE :
@@ -834,7 +834,17 @@ public class JavaProject
return; // setting == IGNORE
}
break;
-
+ case IJavaModelStatusConstants.OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE :
+ isOutputOverlapping = true;
+ setting = getOption(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, true);
+ if (JavaCore.ERROR.equals(setting)) {
+ severity = IMarker.SEVERITY_ERROR;
+ } else if (JavaCore.WARNING.equals(setting)) {
+ severity = IMarker.SEVERITY_WARNING;
+ } else {
+ return; // setting == IGNORE
+ }
+ break;
default:
IPath path = status.getPath();
if (path != null) arguments = new String[] { path.toString() };
@@ -856,6 +866,7 @@ public class JavaProject
IMarker.LOCATION,
IJavaModelMarker.CYCLE_DETECTED,
IJavaModelMarker.CLASSPATH_FILE_FORMAT,
+ IJavaModelMarker.OUTPUT_OVERLAPPING_SOURCE,
IJavaModelMarker.ID,
IJavaModelMarker.ARGUMENTS ,
IJavaModelMarker.CATEGORY_ID,
@@ -867,6 +878,7 @@ public class JavaProject
Messages.classpath_buildPath,
isCycleProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
isClasspathFileFormatProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
+ isOutputOverlapping ? "true" : "false", //$NON-NLS-1$ //$NON-NLS-2$
new Integer(status.getCode()),
Util.getProblemArgumentsForMarker(arguments) ,
new Integer(CategorizedProblem.CAT_BUILDPATH),
@@ -1387,18 +1399,20 @@ public class JavaProject
/**
* Remove all markers denoting classpath problems
*/ //TODO (philippe) should improve to use a bitmask instead of booleans (CYCLE, FORMAT, VALID)
- protected void flushClasspathProblemMarkers(boolean flushCycleMarkers, boolean flushClasspathFormatMarkers) {
+ protected void flushClasspathProblemMarkers(boolean flushCycleMarkers, boolean flushClasspathFormatMarkers, boolean flushOverlappingOutputMarkers) {
try {
if (this.project.isAccessible()) {
IMarker[] markers = this.project.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
for (int i = 0, length = markers.length; i < length; i++) {
IMarker marker = markers[i];
- if (flushCycleMarkers && flushClasspathFormatMarkers) {
+ if (flushCycleMarkers && flushClasspathFormatMarkers && flushOverlappingOutputMarkers) {
marker.delete();
} else {
String cycleAttr = (String)marker.getAttribute(IJavaModelMarker.CYCLE_DETECTED);
String classpathFileFormatAttr = (String)marker.getAttribute(IJavaModelMarker.CLASSPATH_FILE_FORMAT);
+ String overlappingOutputAttr = (String) marker.getAttribute(IJavaModelMarker.OUTPUT_OVERLAPPING_SOURCE);
if ((flushCycleMarkers == (cycleAttr != null && cycleAttr.equals("true"))) //$NON-NLS-1$
+ && (flushOverlappingOutputMarkers == (overlappingOutputAttr != null && overlappingOutputAttr.equals("true"))) //$NON-NLS-1$
&& (flushClasspathFormatMarkers == (classpathFileFormatAttr != null && classpathFileFormatAttr.equals("true")))){ //$NON-NLS-1$
marker.delete();
}
@@ -1545,6 +1559,7 @@ public class JavaProject
propertyName.equals(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS) ||
propertyName.equals(JavaCore.CORE_INCOMPLETE_CLASSPATH) ||
propertyName.equals(JavaCore.CORE_CIRCULAR_CLASSPATH) ||
+ propertyName.equals(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE) ||
propertyName.equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL))
{
manager.deltaState.addClasspathValidation(JavaProject.this);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
index 59c69cec5..d08dff54f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
@@ -987,6 +987,13 @@ public class NameLookup implements SuffixConstants {
break;
case IPackageFragmentRoot.K_SOURCE :
seekTypesInSourcePackage(matchName, pkg, firstDot, partialMatch, topLevelTypeName, acceptFlags, requestor);
+ if (matchName.indexOf('$') != -1) {
+ matchName= matchName.replace('$', '.');
+ firstDot = matchName.indexOf('.');
+ if (!partialMatch)
+ topLevelTypeName = firstDot == -1 ? matchName : matchName.substring(0, firstDot);
+ seekTypesInSourcePackage(matchName, pkg, firstDot, partialMatch, topLevelTypeName, acceptFlags, requestor);
+ }
break;
default :
return;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
index 96238136d..ec0ccf277 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
@@ -114,6 +114,7 @@ public class SetClasspathOperation extends ChangeClasspathOperation {
IJavaModelStatus status = super.verify();
if (!status.isOK())
return status;
+ this.project.flushClasspathProblemMarkers(false, false, true);
return ClasspathEntry.validateClasspath( this.project, this.newRawClasspath, this.newOutputLocation);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index 3b170b51b..fda0e8fa1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -46,7 +46,7 @@ private long previousStructuralBuildTime;
private StringSet structurallyChangedTypes;
public static int MaxStructurallyChangedTypes = 100; // keep track of ? structurally changed types, otherwise consider all to be changed
-public static final byte VERSION = 0x0019; // fix for 325755
+public static final byte VERSION = 0x001A; // fix for 287164
static final byte SOURCE_FOLDER = 1;
static final byte BINARY_FOLDER = 2;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BootstrapMethodsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BootstrapMethodsAttribute.java
new file mode 100644
index 000000000..b196927ea
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BootstrapMethodsAttribute.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IBootstrapMethodsAttribute;
+import org.eclipse.jdt.core.util.IBootstrapMethodsEntry;
+import org.eclipse.jdt.core.util.IConstantPool;
+
+/**
+ * Default implementation of IBootstrapMethodsAttribute.
+ */
+public class BootstrapMethodsAttribute extends ClassFileAttribute implements IBootstrapMethodsAttribute {
+ private static final IBootstrapMethodsEntry[] NO_ENTRIES = new IBootstrapMethodsEntry[0];
+
+ private IBootstrapMethodsEntry[] entries;
+ private int numberOfBootstrapMethods;
+
+ /**
+ * Constructor for BootstrapMethodsAttribute.
+ * @param classFileBytes
+ * @param constantPool
+ * @param offset
+ * @throws ClassFormatException
+ */
+ public BootstrapMethodsAttribute(
+ byte[] classFileBytes,
+ IConstantPool constantPool,
+ int offset) throws ClassFormatException {
+ super(classFileBytes, constantPool, offset);
+ this.numberOfBootstrapMethods = u2At(classFileBytes, 6, offset);
+ final int length = this.numberOfBootstrapMethods;
+ if (length != 0) {
+ int readOffset = 8;
+ this.entries = new IBootstrapMethodsEntry[length];
+ for (int i = 0; i < length; i++) {
+ this.entries[i] = new BootstrapMethodsEntry(classFileBytes, constantPool, offset + readOffset);
+ readOffset += 8;
+ }
+ } else {
+ this.entries = NO_ENTRIES;
+ }
+ }
+
+ /**
+ * @see IBootstrapMethodsAttribute#getBootstrapMethods()
+ */
+ public IBootstrapMethodsEntry[] getBootstrapMethods() {
+ return this.entries;
+ }
+
+ public int getBootstrapMethodsLength() {
+ return this.numberOfBootstrapMethods;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BootstrapMethodsEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BootstrapMethodsEntry.java
new file mode 100644
index 000000000..e444dbd81
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BootstrapMethodsEntry.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IBootstrapMethodsEntry;
+import org.eclipse.jdt.core.util.IConstantPool;
+
+/**
+ * Default implementation of {@link IBootstrapMethodsEntry}
+ */
+public class BootstrapMethodsEntry
+ extends ClassFileStruct
+ implements IBootstrapMethodsEntry {
+
+ private int bootstrapMethodReference;
+ private int[] bootstrapArguments;
+
+ public BootstrapMethodsEntry(byte classFileBytes[], IConstantPool constantPool, int offset) throws ClassFormatException {
+ this.bootstrapMethodReference = u2At(classFileBytes, 0, offset);
+ int length = u2At(classFileBytes, 2, offset);
+ int[] arguments = new int[length];
+ int position = 4;
+ for (int i = 0; i < length; i++) {
+ arguments[i] = u2At(classFileBytes, position, offset);
+ position += 2;
+ }
+ this.bootstrapArguments = arguments;
+ }
+
+ /**
+ * @see IBootstrapMethodsEntry#getBootstrapArguments()
+ */
+ public int[] getBootstrapArguments() {
+ return this.bootstrapArguments;
+ }
+
+ /**
+ * @see IBootstrapMethodsEntry#getBootstrapMethodReference()
+ */
+ public int getBootstrapMethodReference() {
+ return this.bootstrapMethodReference;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java
index 19b80dcc3..0426dc431 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -140,6 +140,18 @@ public class ClassFileReader extends ClassFileStruct implements IClassFileReader
constantPoolOffsets[i] = readOffset;
readOffset += IConstantPoolConstant.CONSTANT_NameAndType_SIZE;
break;
+ case IConstantPoolConstant.CONSTANT_MethodHandle :
+ constantPoolOffsets[i] = readOffset;
+ readOffset += IConstantPoolConstant.CONSTANT_MethodHandle_SIZE;
+ break;
+ case IConstantPoolConstant.CONSTANT_MethodType :
+ constantPoolOffsets[i] = readOffset;
+ readOffset += IConstantPoolConstant.CONSTANT_MethodType_SIZE;
+ break;
+ case IConstantPoolConstant.CONSTANT_InvokeDynamic :
+ constantPoolOffsets[i] = readOffset;
+ readOffset += IConstantPoolConstant.CONSTANT_InvokeDynamic_SIZE;
+ break;
default:
throw new ClassFormatException(ClassFormatException.INVALID_TAG_CONSTANT);
}
@@ -261,6 +273,8 @@ public class ClassFileReader extends ClassFileStruct implements IClassFileReader
this.attributes[attributesIndex++] = new RuntimeVisibleAnnotationsAttribute(classFileBytes, this.constantPool, readOffset);
} else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS)) {
this.attributes[attributesIndex++] = new RuntimeInvisibleAnnotationsAttribute(classFileBytes, this.constantPool, readOffset);
+ } else if (equals(attributeName, IAttributeNamesConstants.BOOTSTRAP_METHODS)) {
+ this.attributes[attributesIndex++] = new BootstrapMethodsAttribute(classFileBytes, this.constantPool, readOffset);
} else {
this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, this.constantPool, readOffset);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java
index 82ba955ae..a281ab0df 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -1049,14 +1049,13 @@ public class CodeAttribute extends ClassFileAttribute implements ICodeAttribute
case IOpcodeMnemonics.INVOKEDYNAMIC :
index = u2At(this.classFileBytes, 1, pc);
constantPoolEntry = this.constantPool.decodeEntry(index);
- if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_NameAndType) {
+ if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_InvokeDynamic) {
throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
}
visitor._invokedynamic(
pc - this.codeOffset,
index,
- this.constantPool.decodeEntry(constantPoolEntry.getNameAndTypeInfoNameIndex()),
- this.constantPool.decodeEntry(constantPoolEntry.getNameAndTypeInfoDescriptorIndex()));
+ constantPoolEntry);
pc += 5;
break;
case IOpcodeMnemonics.NEW :
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java
index aeeee24fc..a9c4699b2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -33,19 +33,28 @@ public class ConstantPool extends ClassFileStruct implements IConstantPool {
* @see IConstantPool#decodeEntry(int)
*/
public IConstantPoolEntry decodeEntry(int index) {
- ConstantPoolEntry constantPoolEntry = new ConstantPoolEntry();
- constantPoolEntry.reset();
+ ConstantPoolEntry constantPoolEntry = null;
int kind = getEntryKind(index);
- constantPoolEntry.setKind(kind);
switch(kind) {
case IConstantPoolConstant.CONSTANT_Class :
+ constantPoolEntry = new ConstantPoolEntry();
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
constantPoolEntry.setClassInfoNameIndex(u2At(this.classFileBytes, 1, this.constantPoolOffset[index]));
constantPoolEntry.setClassInfoName(getUtf8ValueAt(constantPoolEntry.getClassInfoNameIndex()));
break;
case IConstantPoolConstant.CONSTANT_Double :
+ constantPoolEntry = new ConstantPoolEntry();
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
constantPoolEntry.setDoubleValue(doubleAt(this.classFileBytes, 1, this.constantPoolOffset[index]));
break;
case IConstantPoolConstant.CONSTANT_Fieldref :
+ constantPoolEntry = new ConstantPoolEntry();
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
constantPoolEntry.setClassIndex(u2At(this.classFileBytes, 1, this.constantPoolOffset[index]));
int declaringClassIndex = u2At(this.classFileBytes, 1, this.constantPoolOffset[constantPoolEntry.getClassIndex()]);
constantPoolEntry.setClassName(getUtf8ValueAt(declaringClassIndex));
@@ -57,6 +66,11 @@ public class ConstantPool extends ClassFileStruct implements IConstantPool {
break;
case IConstantPoolConstant.CONSTANT_Methodref :
case IConstantPoolConstant.CONSTANT_InterfaceMethodref :
+ constantPoolEntry = new ConstantPoolEntry();
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
constantPoolEntry.setClassIndex(u2At(this.classFileBytes, 1, this.constantPoolOffset[index]));
declaringClassIndex = u2At(this.classFileBytes, 1, this.constantPoolOffset[constantPoolEntry.getClassIndex()]);
constantPoolEntry.setClassName(getUtf8ValueAt(declaringClassIndex));
@@ -67,25 +81,76 @@ public class ConstantPool extends ClassFileStruct implements IConstantPool {
constantPoolEntry.setMethodDescriptor(getUtf8ValueAt(methodDescriptorIndex));
break;
case IConstantPoolConstant.CONSTANT_Float :
+ constantPoolEntry = new ConstantPoolEntry();
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
constantPoolEntry.setFloatValue(floatAt(this.classFileBytes, 1, this.constantPoolOffset[index]));
break;
case IConstantPoolConstant.CONSTANT_Integer :
+ constantPoolEntry = new ConstantPoolEntry();
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
constantPoolEntry.setIntegerValue(i4At(this.classFileBytes, 1, this.constantPoolOffset[index]));
break;
case IConstantPoolConstant.CONSTANT_Long :
+ constantPoolEntry = new ConstantPoolEntry();
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
constantPoolEntry.setLongValue(i8At(this.classFileBytes, 1, this.constantPoolOffset[index]));
break;
case IConstantPoolConstant.CONSTANT_NameAndType :
+ constantPoolEntry = new ConstantPoolEntry();
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
constantPoolEntry.setNameAndTypeNameIndex(u2At(this.classFileBytes, 1, this.constantPoolOffset[index]));
constantPoolEntry.setNameAndTypeDescriptorIndex(u2At(this.classFileBytes, 3, this.constantPoolOffset[index]));
break;
case IConstantPoolConstant.CONSTANT_String :
+ constantPoolEntry = new ConstantPoolEntry();
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
constantPoolEntry.setStringIndex(u2At(this.classFileBytes, 1, this.constantPoolOffset[index]));
constantPoolEntry.setStringValue(getUtf8ValueAt(constantPoolEntry.getStringIndex()));
break;
case IConstantPoolConstant.CONSTANT_Utf8 :
+ constantPoolEntry = new ConstantPoolEntry();
+ constantPoolEntry.reset();
+ constantPoolEntry.setKind(kind);
constantPoolEntry.setUtf8Length(u2At(this.classFileBytes, 1, this.constantPoolOffset[index]));
constantPoolEntry.setUtf8Value(getUtf8ValueAt(index));
+ break;
+ case IConstantPoolConstant.CONSTANT_MethodHandle :
+ ConstantPoolEntry2 constantPoolEntry2 = new ConstantPoolEntry2();
+ constantPoolEntry2.reset();
+ constantPoolEntry2.setKind(kind);
+ constantPoolEntry2.setReferenceKind(u1At(this.classFileBytes, 1, this.constantPoolOffset[index]));
+ constantPoolEntry2.setReferenceIndex(u2At(this.classFileBytes, 2, this.constantPoolOffset[index]));
+ constantPoolEntry = constantPoolEntry2;
+ break;
+ case IConstantPoolConstant.CONSTANT_MethodType :
+ constantPoolEntry2 = new ConstantPoolEntry2();
+ constantPoolEntry2.reset();
+ constantPoolEntry2.setKind(kind);
+ methodDescriptorIndex = u2At(this.classFileBytes, 1, this.constantPoolOffset[index]);
+ constantPoolEntry2.setDescriptorIndex(methodDescriptorIndex);
+ constantPoolEntry2.setMethodDescriptor(getUtf8ValueAt(methodDescriptorIndex));
+ constantPoolEntry = constantPoolEntry2;
+ break;
+ case IConstantPoolConstant.CONSTANT_InvokeDynamic :
+ constantPoolEntry2 = new ConstantPoolEntry2();
+ constantPoolEntry2.reset();
+ constantPoolEntry2.setKind(kind);
+ constantPoolEntry2.setBootstrapMethodAttributeIndex(u2At(this.classFileBytes, 1, this.constantPoolOffset[index]));
+ int nameAndTypeIndex = u2At(this.classFileBytes, 3, this.constantPoolOffset[index]);
+ constantPoolEntry2.setNameAndTypeIndex(nameAndTypeIndex);
+ methodNameIndex = u2At(this.classFileBytes, 1, this.constantPoolOffset[nameAndTypeIndex]);
+ methodDescriptorIndex = u2At(this.classFileBytes, 3, this.constantPoolOffset[nameAndTypeIndex]);
+ constantPoolEntry2.setMethodName(getUtf8ValueAt(methodNameIndex));
+ constantPoolEntry2.setMethodDescriptor(getUtf8ValueAt(methodDescriptorIndex));
+ constantPoolEntry = constantPoolEntry2;
+ break;
}
return constantPoolEntry;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry.java
index 55cc17027..9f9cae664 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -341,6 +341,7 @@ public class ConstantPoolEntry implements IConstantPoolEntry {
/**
* Sets the methodDescriptor.
+ *
* @param methodDescriptor The methodDescriptor to set
*/
public void setMethodDescriptor(char[] methodDescriptor) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry2.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry2.java
new file mode 100644
index 000000000..c6c968625
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPoolEntry2.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.IConstantPoolEntry2;
+
+/**
+ * Default implementation of IConstantPoolEntry
+ *
+ * @since 2.0
+ */
+public class ConstantPoolEntry2 extends ConstantPoolEntry implements IConstantPoolEntry2 {
+
+ private int descriptorIndex;
+ private int referenceKind;
+ private int referenceIndex;
+ private int bootstrapMethodAttributeIndex;
+
+ public int getDescriptorIndex() {
+ return this.descriptorIndex;
+ }
+
+ public int getReferenceKind() {
+ return this.referenceKind;
+ }
+
+ public int getReferenceIndex() {
+ return this.referenceIndex;
+ }
+
+ public int getBootstrapMethodAttributeIndex() {
+ return this.bootstrapMethodAttributeIndex;
+ }
+
+ public void setDescriptorIndex(int descriptorIndex) {
+ this.descriptorIndex = descriptorIndex;
+ }
+
+ public void setReferenceKind(int referenceKind) {
+ this.referenceKind = referenceKind;
+ }
+
+ public void setReferenceIndex(int referenceIndex) {
+ this.referenceIndex = referenceIndex;
+ }
+
+ public void setBootstrapMethodAttributeIndex(int bootstrapMethodAttributeIndex) {
+ this.bootstrapMethodAttributeIndex = bootstrapMethodAttributeIndex;
+ }
+
+ public void reset() {
+ super.reset();
+ this.descriptorIndex = 0;
+ this.referenceKind = 0;
+ this.referenceIndex = 0;
+ this.bootstrapMethodAttributeIndex = 0;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java
index d94dd4e28..b5fe2abab 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -17,6 +17,7 @@ import org.eclipse.jdt.core.util.IBytecodeVisitor;
import org.eclipse.jdt.core.util.ICodeAttribute;
import org.eclipse.jdt.core.util.IConstantPoolConstant;
import org.eclipse.jdt.core.util.IConstantPoolEntry;
+import org.eclipse.jdt.core.util.IConstantPoolEntry2;
import org.eclipse.jdt.core.util.ILocalVariableAttribute;
import org.eclipse.jdt.core.util.ILocalVariableTableEntry;
import org.eclipse.jdt.core.util.OpcodeStringValues;
@@ -1491,7 +1492,7 @@ public class DefaultBytecodeVisitor implements IBytecodeVisitor {
writeNewLine();
}
/**
- * @see IBytecodeVisitor#_invokedynamic(int, int, IConstantPoolEntry, IConstantPoolEntry)
+ * @see IBytecodeVisitor#_invokedynamic(int, int, IConstantPoolEntry)
*/
public void _invokedynamic(
int pc,
@@ -1513,6 +1514,30 @@ public class DefaultBytecodeVisitor implements IBytecodeVisitor {
writeNewLine();
}
/**
+ * @see IBytecodeVisitor#_invokedynamic(int, int, IConstantPoolEntry)
+ */
+ public void _invokedynamic(
+ int pc,
+ int index,
+ IConstantPoolEntry invokeDynamicEntry) {
+
+ dumpPcNumber(pc);
+ IConstantPoolEntry2 entry = (IConstantPoolEntry2) invokeDynamicEntry;
+ this.buffer.append(Messages.bind(Messages.classformat_invokedynamic,
+ new String[] {
+ OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKEDYNAMIC],
+ Integer.toString(index),
+ Integer.toString(entry.getBootstrapMethodAttributeIndex()),
+ Util.toString(
+ null,
+ entry.getMethodName(),
+ entry.getMethodDescriptor(),
+ true,
+ isCompact())
+ }));
+ writeNewLine();
+ }
+ /**
* @see IBytecodeVisitor#_invokeinterface(int, int, byte, IConstantPoolEntry)
*/
public void _invokeinterface(
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
index c54fd7395..067a219a2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
@@ -741,7 +741,7 @@ public class Disassembler extends ClassFileBytesDisassembler {
final int classNameLength = className.length;
final int accessFlags = classFileReader.getAccessFlags();
final boolean isEnum = (accessFlags & IModifierConstants.ACC_ENUM) != 0;
-
+
StringBuffer buffer = new StringBuffer();
ISourceAttribute sourceAttribute = classFileReader.getSourceFileAttribute();
IClassFileAttribute classFileAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.SIGNATURE);
@@ -788,7 +788,7 @@ public class Disassembler extends ClassFileBytesDisassembler {
}
}
final int lastDotIndexInClassName = CharOperation.lastIndexOf('.', className);
-
+
if (checkMode(mode, WORKING_COPY) && lastDotIndexInClassName != -1) {
// we print a package declaration
buffer.append("package ");//$NON-NLS-1$
@@ -796,11 +796,13 @@ public class Disassembler extends ClassFileBytesDisassembler {
buffer.append(';');
writeNewLine(buffer, lineSeparator, 0);
}
-
+
IInnerClassesAttribute innerClassesAttribute = classFileReader.getInnerClassesAttribute();
IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
-
+
+ IClassFileAttribute bootstrapMethods = Util.getAttribute(classFileReader, IAttributeNamesConstants.BOOTSTRAP_METHODS);
+
if (checkMode(mode, DETAILED)) {
// disassemble compact version of annotations
if (runtimeInvisibleAnnotationsAttribute != null) {
@@ -838,7 +840,7 @@ public class Disassembler extends ClassFileBytesDisassembler {
}
}
}
-
+
final boolean isAnnotation = (accessFlags & IModifierConstants.ACC_ANNOTATION) != 0;
boolean isInterface = false;
if (isEnum) {
@@ -852,7 +854,7 @@ public class Disassembler extends ClassFileBytesDisassembler {
buffer.append("interface "); //$NON-NLS-1$
isInterface = true;
}
-
+
if (checkMode(mode, WORKING_COPY)) {
// we print the simple class name
final int start = lastDotIndexInClassName + 1;
@@ -864,7 +866,7 @@ public class Disassembler extends ClassFileBytesDisassembler {
} else {
buffer.append(className);
}
-
+
char[] superclassName = classFileReader.getSuperclassName();
if (superclassName != null) {
CharOperation.replace(superclassName, '/', '.');
@@ -917,8 +919,17 @@ public class Disassembler extends ClassFileBytesDisassembler {
if (signatureAttribute != null) {
remainingAttributesLength--;
}
- if (innerClassesAttribute != null || enclosingMethodAttribute != null || remainingAttributesLength != 0) {
- writeNewLine(buffer, lineSeparator, 0);
+ if (bootstrapMethods != null) {
+ remainingAttributesLength--;
+ }
+ if (innerClassesAttribute != null
+ || enclosingMethodAttribute != null
+ || bootstrapMethods != null
+ || remainingAttributesLength != 0) {
+ // this test is to ensure we don't insert more than one line separator
+ if (buffer.lastIndexOf(lineSeparator) != buffer.length() - lineSeparator.length()) {
+ writeNewLine(buffer, lineSeparator, 0);
+ }
}
if (innerClassesAttribute != null) {
disassemble(innerClassesAttribute, buffer, lineSeparator, 1);
@@ -926,6 +937,9 @@ public class Disassembler extends ClassFileBytesDisassembler {
if (enclosingMethodAttribute != null) {
disassemble(enclosingMethodAttribute, buffer, lineSeparator, 0);
}
+ if (bootstrapMethods != null) {
+ disassemble((IBootstrapMethodsAttribute) bootstrapMethods, buffer, lineSeparator, 0);
+ }
if (checkMode(mode, SYSTEM)) {
if (runtimeVisibleAnnotationsAttribute != null) {
disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode);
@@ -937,13 +951,14 @@ public class Disassembler extends ClassFileBytesDisassembler {
for (int i = 0; i < length; i++) {
IClassFileAttribute attribute = attributes[i];
if (attribute != innerClassesAttribute
- && attribute != sourceAttribute
- && attribute != signatureAttribute
- && attribute != enclosingMethodAttribute
- && attribute != runtimeInvisibleAnnotationsAttribute
- && attribute != runtimeVisibleAnnotationsAttribute
- && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
- && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
+ && attribute != sourceAttribute
+ && attribute != signatureAttribute
+ && attribute != enclosingMethodAttribute
+ && attribute != runtimeInvisibleAnnotationsAttribute
+ && attribute != runtimeVisibleAnnotationsAttribute
+ && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
+ && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)
+ && attribute != bootstrapMethods) {
disassemble(attribute, buffer, lineSeparator, 0, mode);
}
}
@@ -1408,9 +1423,73 @@ public class Disassembler extends ClassFileBytesDisassembler {
Integer.toString(i),
decodeStringValue(new String(constantPoolEntry.getUtf8Value()))}));
break;
+ case IConstantPoolConstant.CONSTANT_MethodHandle :
+ IConstantPoolEntry2 entry2 = (IConstantPoolEntry2) constantPoolEntry;
+ buffer.append(
+ Messages.bind(Messages.disassembler_constantpool_methodhandle,
+ new String[] {
+ Integer.toString(i),
+ getReferenceKind(entry2.getReferenceKind()),
+ Integer.toString(entry2.getReferenceIndex()),
+ }));
+ break;
+ case IConstantPoolConstant.CONSTANT_MethodType :
+ entry2 = (IConstantPoolEntry2) constantPoolEntry;
+ buffer.append(
+ Messages.bind(Messages.disassembler_constantpool_methodtype,
+ new String[] {
+ Integer.toString(i),
+ Integer.toString(entry2.getDescriptorIndex()),
+ String.valueOf(entry2.getMethodDescriptor()),
+ }));
+ break;
+ case IConstantPoolConstant.CONSTANT_InvokeDynamic :
+ entry2 = (IConstantPoolEntry2) constantPoolEntry;
+ buffer.append(
+ Messages.bind(Messages.disassembler_constantpool_invokedynamic,
+ new String[] {
+ Integer.toString(i),
+ Integer.toString(entry2.getBootstrapMethodAttributeIndex()),
+ Integer.toString(entry2.getNameAndTypeIndex()),
+ new String(constantPoolEntry.getMethodName()),
+ new String(constantPoolEntry.getMethodDescriptor())
+ }));
}
}
}
+
+ private String getReferenceKind(int referenceKind) {
+ String message = null;
+ switch(referenceKind) {
+ case IConstantPoolConstant.METHOD_TYPE_REF_GetField :
+ message = Messages.disassembler_method_type_ref_getfield;
+ break;
+ case IConstantPoolConstant.METHOD_TYPE_REF_GetStatic :
+ message = Messages.disassembler_method_type_ref_getstatic;
+ break;
+ case IConstantPoolConstant.METHOD_TYPE_REF_PutField :
+ message = Messages.disassembler_method_type_ref_putfield;
+ break;
+ case IConstantPoolConstant.METHOD_TYPE_REF_PutStatic :
+ message = Messages.disassembler_method_type_ref_putstatic;
+ break;
+ case IConstantPoolConstant.METHOD_TYPE_REF_InvokeInterface :
+ message = Messages.disassembler_method_type_ref_invokeinterface;
+ break;
+ case IConstantPoolConstant.METHOD_TYPE_REF_InvokeSpecial :
+ message = Messages.disassembler_method_type_ref_invokespecial;
+ break;
+ case IConstantPoolConstant.METHOD_TYPE_REF_InvokeStatic :
+ message = Messages.disassembler_method_type_ref_invokestatic;
+ break;
+ case IConstantPoolConstant.METHOD_TYPE_REF_InvokeVirtual :
+ message = Messages.disassembler_method_type_ref_invokevirtual;
+ break;
+ default :
+ message = Messages.disassembler_method_type_ref_newinvokespecial;
+ }
+ return Messages.bind(message, new String[] { Integer.toString(referenceKind) });
+ }
private void disassemble(IEnclosingMethodAttribute enclosingMethodAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
writeNewLine(buffer, lineSeparator, tabNumber + 1);
@@ -1669,6 +1748,46 @@ public class Disassembler extends ClassFileBytesDisassembler {
}
}
+ private void disassemble(IBootstrapMethodsAttribute bootstrapMethodsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ buffer.append(Messages.disassembler_bootstrapmethodattributesheader);
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ IBootstrapMethodsEntry[] entries = bootstrapMethodsAttribute.getBootstrapMethods();
+ int length = entries.length;
+ for (int i = 0; i < length; i++) {
+ if (i != 0) {
+ buffer.append(Messages.disassembler_comma);
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ }
+ IBootstrapMethodsEntry entry = entries[i];
+ buffer.append(
+ Messages.bind(
+ Messages.disassembler_bootstrapmethodentry,
+ new String[] {
+ Integer.toString(i),
+ Integer.toString(entry.getBootstrapMethodReference()),
+ getArguments(entry.getBootstrapArguments())
+ }));
+ }
+ }
+
+ private String getArguments(int[] arguments) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('{');
+ for (int i = 0, max = arguments.length; i < max; i++) {
+ if (i != 0) {
+ buffer.append(Messages.disassembler_comma);
+ }
+ buffer.append(
+ Messages.bind(
+ Messages.disassembler_bootstrapmethodentry_argument,
+ new String[] {
+ Integer.toString(arguments[i]),
+ }));
+ }
+ buffer.append('}');
+ return String.valueOf(buffer);
+ }
private void disassemble(int index, IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
IAnnotation[] annotations = parameterAnnotation.getAnnotations();
writeNewLine(buffer, lineSeparator, tabNumber + 1);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java
index 75ecbabdd..ff1cf8326 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java
@@ -259,6 +259,9 @@ public final class Messages extends NLS {
public static String disassembler_inner_accessflags;
public static String disassembler_genericattributeheader;
public static String disassembler_signatureattributeheader;
+ public static String disassembler_bootstrapmethodattributesheader;
+ public static String disassembler_bootstrapmethodentry;
+ public static String disassembler_bootstrapmethodentry_argument;
public static String disassembler_indentation;
public static String disassembler_constantpoolindex;
public static String disassembler_space;
@@ -278,6 +281,9 @@ public final class Messages extends NLS {
public static String disassembler_constantpool_methodref;
public static String disassembler_constantpool_name_and_type;
public static String disassembler_constantpool_utf8;
+ public static String disassembler_constantpool_methodhandle;
+ public static String disassembler_constantpool_methodtype;
+ public static String disassembler_constantpool_invokedynamic;
public static String disassembler_annotationdefaultheader;
public static String disassembler_annotationdefaultvalue;
public static String disassembler_annotationenumvalue;
@@ -348,6 +354,16 @@ public final class Messages extends NLS {
public static String disassembler_frame_same_frame;
public static String disassembler_frame_same_locals_1_stack_item;
public static String code_assist_internal_error;
+
+ public static String disassembler_method_type_ref_getfield;
+ public static String disassembler_method_type_ref_putfield;
+ public static String disassembler_method_type_ref_getstatic;
+ public static String disassembler_method_type_ref_putstatic;
+ public static String disassembler_method_type_ref_invokestatic;
+ public static String disassembler_method_type_ref_invokevirtual;
+ public static String disassembler_method_type_ref_invokespecial;
+ public static String disassembler_method_type_ref_invokeinterface;
+ public static String disassembler_method_type_ref_newinvokespecial;
static {
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
index e75e56ba7..5af88dbe8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
@@ -285,6 +285,9 @@ disassembler_genericattributeheader = Attribute: {0} Length: {1}
disassembler_stackmaptableattributeheader = Stack map table: number of frames {0}
disassembler_stackmapattributeheader = Stack map : number of frames {0}
disassembler_signatureattributeheader = // Signature: {0}
+disassembler_bootstrapmethodattributesheader = Bootstrap methods:
+disassembler_bootstrapmethodentry = {0} : # {1} arguments: {2}
+disassembler_bootstrapmethodentry_argument = #{0}
disassembler_indentation = \
disassembler_constantpoolindex =\ #
disassembler_space = \
@@ -304,6 +307,9 @@ disassembler_constantpool_interfacemethodref = constant #{0} interface_method_re
disassembler_constantpool_methodref = constant #{0} method_ref: #{1}.#{2} {3}.{4} {5}
disassembler_constantpool_name_and_type = constant #{0} name_and_type: #{1}.#{2} {3} {4}
disassembler_constantpool_utf8 = constant #{0} utf8: "{1}"
+disassembler_constantpool_methodhandle = constant #{0} method handle: {1} #{2}
+disassembler_constantpool_methodtype = constant #{0} method type: #{1} {2}
+disassembler_constantpool_invokedynamic = constant #{0} invoke dynamic: #{1} #{2} {3} {4}
disassembler_annotationdefaultheader = Annotation Default:\
disassembler_annotationdefaultvalue= {0} (constant type)
disassembler_annotationenumvalue = {2}.{3}(enum type #{0}.#{1})
@@ -323,6 +329,15 @@ disassembler_frame_same_locals_1_stack_item_extended=[pc: {0}, same_locals_1_sta
disassembler_frame_chop=[pc: {0}, chop {1} local(s)]
disassembler_frame_same_frame_extended=[pc: {0}, same_extended]
disassembler_frame_append=[pc: {0}, append: {1}]
+disassembler_method_type_ref_getfield = getfield ({0})
+disassembler_method_type_ref_putfield = putfield ({0})
+disassembler_method_type_ref_getstatic = getstatic ({0})
+disassembler_method_type_ref_putstatic = putstatic ({0})
+disassembler_method_type_ref_invokestatic = invokestatic ({0})
+disassembler_method_type_ref_invokevirtual = invokevirtual ({0})
+disassembler_method_type_ref_invokeinterface = invokeinterface ({0})
+disassembler_method_type_ref_invokespecial = invokespecial ({0})
+disassembler_method_type_ref_newinvokespecial = newinvokespecial ({0})
# {0} = offset delta
# {1} = number of locals
# {2} = locals
@@ -358,7 +373,7 @@ classformat_new = {0} {2} [{1}]
classformat_iinc = {0} {1} {2}{3}
classformat_invokespecial ={0} {2} [{1}]
classformat_invokeinterface ={0} {3} [{1}] [nargs: {2}]
-classformat_invokedynamic={0} {2} [{1}]
+classformat_invokedynamic={0} {2} {3} [{1}]
classformat_invokestatic ={0} {2} [{1}]
classformat_invokevirtual ={0} {2} [{1}]
classformat_getfield ={0} {2}.{3} : {4} [{1}]
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
index 09e058bf3..753c785ed 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
@@ -1475,7 +1475,7 @@ protected void locatePackageDeclarations(SearchPattern searchPattern, SearchPart
}
//*/
protected IType lookupType(ReferenceBinding typeBinding) {
- if (typeBinding == null) return null;
+ if (typeBinding == null || !typeBinding.isValidBinding()) return null;
char[] packageName = typeBinding.qualifiedPackageName();
IPackageFragment[] pkgs = this.nameLookup.findPackageFragments(

Back to the top