Prepared better HEREDOC support; see comment for bug #1319276
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / flow / FinallyFlowContext.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.flow;
12
13 import net.sourceforge.phpdt.internal.compiler.ast.ASTNode;
14 import net.sourceforge.phpdt.internal.compiler.ast.Reference;
15 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
16 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
17 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
18 import net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding;
19
20 /**
21  * Reflects the context of code analysis, keeping track of enclosing
22  *      try statements, exception handlers, etc...
23  */
24 public class FinallyFlowContext extends FlowContext {
25         
26         Reference finalAssignments[];
27         VariableBinding finalVariables[];
28         int assignCount;
29         
30         public FinallyFlowContext(FlowContext parent, ASTNode associatedNode) {
31                 super(parent, associatedNode);
32         }
33
34         /**
35          * Given some contextual initialization info (derived from a try block or a catch block), this 
36          * code will check that the subroutine context does not also initialize a final variable potentially set
37          * redundantly.
38          */
39         public void complainOnRedundantFinalAssignments(
40                 FlowInfo flowInfo,
41                 BlockScope scope) {
42                 for (int i = 0; i < assignCount; i++) {
43                         VariableBinding variable = finalVariables[i];
44                         if (variable == null) continue;
45                         
46                         boolean complained = false; // remember if have complained on this final assignment
47                         if (variable instanceof FieldBinding) {
48                                 // final field
49                                 if (flowInfo.isPotentiallyAssigned((FieldBinding)variable)) {
50                                         complained = true;
51                                         scope.problemReporter().duplicateInitializationOfBlankFinalField((FieldBinding)variable, finalAssignments[i]);
52                                 }
53                         } else {
54                                 // final local variable
55                                 if (flowInfo.isPotentiallyAssigned((LocalVariableBinding) variable)) {
56                                         complained = true;
57                                         scope.problemReporter().duplicateInitializationOfFinalLocal(
58                                                 (LocalVariableBinding) variable,
59                                                 finalAssignments[i]);
60                                 }
61                         }
62                         // any reference reported at this level is removed from the parent context 
63                         // where it could also be reported again
64                         if (complained) {
65                                 FlowContext currentContext = parent;
66                                 while (currentContext != null) {
67                                         //if (currentContext.isSubRoutine()) {
68                                         currentContext.removeFinalAssignmentIfAny(finalAssignments[i]);
69                                         //}
70                                         currentContext = currentContext.parent;
71                                 }
72                         }
73                 }
74         }
75
76         public String individualToString() {
77                 
78                 StringBuffer buffer = new StringBuffer("Finally flow context"); //$NON-NLS-1$
79                 buffer.append("[finalAssignments count -").append(assignCount).append(']'); //$NON-NLS-1$
80                 return buffer.toString();
81         }
82         
83         public boolean isSubRoutine() {
84                 return true;
85         }
86
87         boolean recordFinalAssignment(
88                 VariableBinding binding,
89                 Reference finalAssignment) {
90                 if (assignCount == 0) {
91                         finalAssignments = new Reference[5];
92                         finalVariables = new VariableBinding[5];
93                 } else {
94                         if (assignCount == finalAssignments.length)
95                                 System.arraycopy(
96                                         finalAssignments,
97                                         0,
98                                         (finalAssignments = new Reference[assignCount * 2]),
99                                         0,
100                                         assignCount);
101                         System.arraycopy(
102                                 finalVariables,
103                                 0,
104                                 (finalVariables = new VariableBinding[assignCount * 2]),
105                                 0,
106                                 assignCount);
107                 };
108                 finalAssignments[assignCount] = finalAssignment;
109                 finalVariables[assignCount++] = binding;
110                 return true;
111         }
112
113         void removeFinalAssignmentIfAny(Reference reference) {
114                 for (int i = 0; i < assignCount; i++) {
115                         if (finalAssignments[i] == reference) {
116                                 finalAssignments[i] = null;
117                                 finalVariables[i] = null;
118                                 return;
119                         }
120                 }
121         }
122 }