Applying pteague's patch (re #685)
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / flow / LoopingFlowContext.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.codegen.Label;
16 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
17 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
18 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
20 import net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding;
21
22 /**
23  * Reflects the context of code analysis, keeping track of enclosing try
24  * statements, exception handlers, etc...
25  */
26 public class LoopingFlowContext extends SwitchFlowContext {
27
28         public Label continueLabel;
29
30         public UnconditionalFlowInfo initsOnContinue = FlowInfo.DEAD_END;
31
32         Reference finalAssignments[];
33
34         VariableBinding finalVariables[];
35
36         int assignCount = 0;
37
38         Scope associatedScope;
39
40         public LoopingFlowContext(FlowContext parent, ASTNode associatedNode,
41                         Label breakLabel, Label continueLabel, Scope associatedScope) {
42                 super(parent, associatedNode, breakLabel);
43                 this.continueLabel = continueLabel;
44                 this.associatedScope = associatedScope;
45         }
46
47         public void complainOnFinalAssignmentsInLoop(BlockScope scope,
48                         FlowInfo flowInfo) {
49                 for (int i = 0; i < assignCount; i++) {
50                         VariableBinding variable = finalVariables[i];
51                         if (variable == null)
52                                 continue;
53                         boolean complained = false; // remember if have complained on this
54                                                                                 // final assignment
55                         if (variable instanceof FieldBinding) {
56                                 if (flowInfo.isPotentiallyAssigned((FieldBinding) variable)) {
57                                         complained = true;
58                                         scope.problemReporter()
59                                                         .duplicateInitializationOfBlankFinalField(
60                                                                         (FieldBinding) variable,
61                                                                         finalAssignments[i]);
62                                 }
63                         } else {
64                                 if (flowInfo
65                                                 .isPotentiallyAssigned((LocalVariableBinding) variable)) {
66                                         complained = true;
67                                         scope.problemReporter()
68                                                         .duplicateInitializationOfFinalLocal(
69                                                                         (LocalVariableBinding) variable,
70                                                                         finalAssignments[i]);
71                                 }
72                         }
73                         // any reference reported at this level is removed from the parent
74                         // context where it
75                         // could also be reported again
76                         if (complained) {
77                                 FlowContext context = parent;
78                                 while (context != null) {
79                                         context.removeFinalAssignmentIfAny(finalAssignments[i]);
80                                         context = context.parent;
81                                 }
82                         }
83                 }
84         }
85
86         public Label continueLabel() {
87                 return continueLabel;
88         }
89
90         public String individualToString() {
91                 StringBuffer buffer = new StringBuffer("Looping flow context"); //$NON-NLS-1$
92                 buffer
93                                 .append("[initsOnBreak -").append(initsOnBreak.toString()).append(']'); //$NON-NLS-1$
94                 buffer
95                                 .append("[initsOnContinue -").append(initsOnContinue.toString()).append(']'); //$NON-NLS-1$
96                 return buffer.toString();
97         }
98
99         public boolean isContinuable() {
100                 return true;
101         }
102
103         public boolean isContinuedTo() {
104                 return initsOnContinue != FlowInfo.DEAD_END;
105         }
106
107         public void recordContinueFrom(FlowInfo flowInfo) {
108
109                 if (!flowInfo.isReachable())
110                         return;
111                 if (initsOnContinue == FlowInfo.DEAD_END) {
112                         initsOnContinue = flowInfo.copy().unconditionalInits();
113                 } else {
114                         initsOnContinue = initsOnContinue.mergedWith(flowInfo
115                                         .unconditionalInits());
116                 }
117                 ;
118         }
119
120         boolean recordFinalAssignment(VariableBinding binding,
121                         Reference finalAssignment) {
122                 // do not consider variables which are defined inside this loop
123                 if (binding instanceof LocalVariableBinding) {
124                         Scope scope = ((LocalVariableBinding) binding).declaringScope;
125                         while ((scope = scope.parent) != null) {
126                                 if (scope == associatedScope)
127                                         return false;
128                         }
129                 }
130                 if (assignCount == 0) {
131                         finalAssignments = new Reference[5];
132                         finalVariables = new VariableBinding[5];
133                 } else {
134                         if (assignCount == finalAssignments.length)
135                                 System.arraycopy(finalAssignments, 0,
136                                                 (finalAssignments = new Reference[assignCount * 2]), 0,
137                                                 assignCount);
138                         System.arraycopy(finalVariables, 0,
139                                         (finalVariables = new VariableBinding[assignCount * 2]), 0,
140                                         assignCount);
141                 }
142                 ;
143                 finalAssignments[assignCount] = finalAssignment;
144                 finalVariables[assignCount++] = binding;
145                 return true;
146         }
147
148         void removeFinalAssignmentIfAny(Reference reference) {
149                 for (int i = 0; i < assignCount; i++) {
150                         if (finalAssignments[i] == reference) {
151                                 finalAssignments[i] = null;
152                                 finalVariables[i] = null;
153                                 return;
154                         }
155                 }
156         }
157 }