misc changes
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / flow / LoopingFlowContext.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v0.5 
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v05.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.NameReference;
15 import net.sourceforge.phpdt.internal.compiler.ast.Reference;
16 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
21 import net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding;
22
23 /**
24  * Reflects the context of code analysis, keeping track of enclosing
25  *      try statements, exception handlers, etc...
26  */
27 public class LoopingFlowContext extends SwitchFlowContext {
28         public Label continueLabel;
29         public UnconditionalFlowInfo initsOnContinue = FlowInfo.DeadEnd;
30         Reference finalAssignments[];
31         VariableBinding finalVariables[];
32         int assignCount = 0;
33         Scope associatedScope;
34         public LoopingFlowContext(
35                 FlowContext parent,
36                 AstNode associatedNode,
37                 Label breakLabel,
38                 Label continueLabel,
39                 Scope associatedScope) {
40                 super(parent, associatedNode, breakLabel);
41                 this.continueLabel = continueLabel;
42                 this.associatedScope = associatedScope;
43         }
44         
45         public void complainOnFinalAssignmentsInLoop(
46                 BlockScope scope,
47                 FlowInfo flowInfo) {
48                 for (int i = 0; i < assignCount; i++) {
49                         VariableBinding variable;
50                         if ((variable = finalVariables[i]) != null) {
51                                 boolean complained; // remember if have complained on this final assignment
52                                 if (variable instanceof FieldBinding) {
53                                         if (complained = flowInfo.isPotentiallyAssigned((FieldBinding) variable)) {
54                                                 scope.problemReporter().duplicateInitializationOfBlankFinalField(
55                                                         (FieldBinding) variable,
56                                                         (NameReference) finalAssignments[i]);
57                                         }
58                                 } else {
59                                         if (complained =
60                                                 flowInfo.isPotentiallyAssigned((LocalVariableBinding) variable)) {
61                                                 scope.problemReporter().duplicateInitializationOfFinalLocal(
62                                                         (LocalVariableBinding) variable,
63                                                         (NameReference) finalAssignments[i]);
64                                         }
65                                 }
66                                 // any reference reported at this level is removed from the parent context where it 
67                                 // could also be reported again
68                                 if (complained) {
69                                         FlowContext context = parent;
70                                         while (context != null) {
71                                                 context.removeFinalAssignmentIfAny(finalAssignments[i]);
72                                                 context = context.parent;
73                                         }
74                                 }
75                         }
76                 }
77         }
78
79         public Label continueLabel() {
80                 return continueLabel;
81         }
82
83         public String individualToString() {
84                 return "Looping flow context"; //$NON-NLS-1$
85         }
86
87         public boolean isContinuable() {
88                 return true;
89         }
90
91         public boolean isContinuedTo() {
92                 return initsOnContinue != FlowInfo.DeadEnd;
93         }
94
95         public void recordContinueFrom(FlowInfo flowInfo) {
96                 if (initsOnContinue == FlowInfo.DeadEnd) {
97                         initsOnContinue = flowInfo.copy().unconditionalInits();
98                 } else {
99                         // ignore if not really reachable (1FKEKRP)
100                         if (flowInfo.isFakeReachable())
101                                 return;
102                         initsOnContinue.mergedWith(flowInfo.unconditionalInits());
103                 };
104         }
105
106         boolean recordFinalAssignment(
107                 VariableBinding binding,
108                 Reference finalAssignment) {
109                 // do not consider variables which are defined inside this loop
110                 if (binding instanceof LocalVariableBinding) {
111                         Scope scope = ((LocalVariableBinding) binding).declaringScope;
112                         while ((scope = scope.parent) != null) {
113                                 if (scope == associatedScope)
114                                         return false;
115                         }
116                 }
117                 if (assignCount == 0) {
118                         finalAssignments = new Reference[5];
119                         finalVariables = new VariableBinding[5];
120                 } else {
121                         if (assignCount == finalAssignments.length)
122                                 System.arraycopy(
123                                         finalAssignments,
124                                         0,
125                                         (finalAssignments = new Reference[assignCount * 2]),
126                                         0,
127                                         assignCount);
128                         System.arraycopy(
129                                 finalVariables,
130                                 0,
131                                 (finalVariables = new VariableBinding[assignCount * 2]),
132                                 0,
133                                 assignCount);
134                 };
135                 finalAssignments[assignCount] = finalAssignment;
136                 finalVariables[assignCount++] = binding;
137                 return true;
138         }
139
140         void removeFinalAssignmentIfAny(Reference reference) {
141                 for (int i = 0; i < assignCount; i++) {
142                         if (finalAssignments[i] == reference) {
143                                 finalAssignments[i] = null;
144                                 finalVariables[i] = null;
145                                 return;
146                         }
147                 }
148         }
149 }