1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.flow;
13 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
14 import org.eclipse.jdt.internal.compiler.ast.Expression;
15 import org.eclipse.jdt.internal.compiler.ast.Reference;
16 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
17 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
18 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
19 import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
22 * Reflects the context of code analysis, keeping track of enclosing
23 * try statements, exception handlers, etc...
25 public class FinallyFlowContext extends FlowContext {
27 Reference[] finalAssignments;
28 VariableBinding[] finalVariables;
31 Expression[] nullReferences;
35 public FinallyFlowContext(FlowContext parent, ASTNode associatedNode) {
36 super(parent, associatedNode);
40 * Given some contextual initialization info (derived from a try block or a catch block), this
41 * code will check that the subroutine context does not also initialize a final variable potentially set
44 public void complainOnDeferredChecks(FlowInfo flowInfo, BlockScope scope) {
46 // check redundant final assignments
47 for (int i = 0; i < assignCount; i++) {
48 VariableBinding variable = finalVariables[i];
49 if (variable == null) continue;
51 boolean complained = false; // remember if have complained on this final assignment
52 if (variable instanceof FieldBinding) {
54 if (flowInfo.isPotentiallyAssigned((FieldBinding)variable)) {
56 scope.problemReporter().duplicateInitializationOfBlankFinalField((FieldBinding)variable, finalAssignments[i]);
59 // final local variable
60 if (flowInfo.isPotentiallyAssigned((LocalVariableBinding) variable)) {
62 scope.problemReporter().duplicateInitializationOfFinalLocal(
63 (LocalVariableBinding) variable,
67 // any reference reported at this level is removed from the parent context
68 // where it could also be reported again
70 FlowContext currentContext = parent;
71 while (currentContext != null) {
72 //if (currentContext.isSubRoutine()) {
73 currentContext.removeFinalAssignmentIfAny(finalAssignments[i]);
75 currentContext = currentContext.parent;
80 // check inconsistent null checks
81 for (int i = 0; i < nullCount; i++) {
82 Expression expression = nullReferences[i];
83 if (expression == null) continue;
84 // final local variable
85 LocalVariableBinding local = expression.localVariableBinding();
86 switch (nullStatus[i]) {
88 if (flowInfo.isDefinitelyNull(local)) {
89 nullReferences[i] = null;
90 this.parent.recordUsingNullReference(scope, local, expression, nullStatus[i], flowInfo);
93 case FlowInfo.NON_NULL :
94 if (flowInfo.isDefinitelyNonNull(local)) {
95 nullReferences[i] = null;
96 this.parent.recordUsingNullReference(scope, local, expression, nullStatus[i], flowInfo);
103 public String individualToString() {
105 StringBuffer buffer = new StringBuffer("Finally flow context"); //$NON-NLS-1$
106 buffer.append("[finalAssignments count - ").append(assignCount).append(']'); //$NON-NLS-1$
107 buffer.append("[nullReferences count - ").append(nullCount).append(']'); //$NON-NLS-1$
108 return buffer.toString();
111 public boolean isSubRoutine() {
115 protected boolean recordFinalAssignment(
116 VariableBinding binding,
117 Reference finalAssignment) {
118 if (assignCount == 0) {
119 finalAssignments = new Reference[5];
120 finalVariables = new VariableBinding[5];
122 if (assignCount == finalAssignments.length)
126 (finalAssignments = new Reference[assignCount * 2]),
132 (finalVariables = new VariableBinding[assignCount * 2]),
136 finalAssignments[assignCount] = finalAssignment;
137 finalVariables[assignCount++] = binding;
141 void removeFinalAssignmentIfAny(Reference reference) {
142 for (int i = 0; i < assignCount; i++) {
143 if (finalAssignments[i] == reference) {
144 finalAssignments[i] = null;
145 finalVariables[i] = null;
151 protected boolean recordNullReference(Expression expression, int status) {
152 if (nullCount == 0) {
153 nullReferences = new Expression[5];
154 nullStatus = new int[5];
156 if (nullCount == nullReferences.length) {
157 System.arraycopy(nullReferences, 0, nullReferences = new Expression[nullCount * 2], 0, nullCount);
158 System.arraycopy(nullStatus, 0, nullStatus = new int[nullCount * 2], 0, nullCount);
161 nullReferences[nullCount] = expression;
162 nullStatus[nullCount++] = status;