1) Need to syncronize also the type of variable values not only the values (makes...
[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 try
22  * statements, exception handlers, etc...
23  */
24 public class FinallyFlowContext extends FlowContext {
25
26         Reference finalAssignments[];
27
28         VariableBinding finalVariables[];
29
30         int assignCount;
31
32         public FinallyFlowContext(FlowContext parent, ASTNode associatedNode) {
33                 super(parent, associatedNode);
34         }
35
36         /**
37          * Given some contextual initialization info (derived from a try block or a
38          * catch block), this code will check that the subroutine context does not
39          * also initialize a final variable potentially set redundantly.
40          */
41         public void complainOnRedundantFinalAssignments(FlowInfo flowInfo,
42                         BlockScope scope) {
43                 for (int i = 0; i < assignCount; i++) {
44                         VariableBinding variable = finalVariables[i];
45                         if (variable == null)
46                                 continue;
47
48                         boolean complained = false; // remember if have complained on this
49                                                                                 // final assignment
50                         if (variable instanceof FieldBinding) {
51                                 // final field
52                                 if (flowInfo.isPotentiallyAssigned((FieldBinding) variable)) {
53                                         complained = true;
54                                         scope.problemReporter()
55                                                         .duplicateInitializationOfBlankFinalField(
56                                                                         (FieldBinding) variable,
57                                                                         finalAssignments[i]);
58                                 }
59                         } else {
60                                 // final local variable
61                                 if (flowInfo
62                                                 .isPotentiallyAssigned((LocalVariableBinding) variable)) {
63                                         complained = true;
64                                         scope.problemReporter()
65                                                         .duplicateInitializationOfFinalLocal(
66                                                                         (LocalVariableBinding) variable,
67                                                                         finalAssignments[i]);
68                                 }
69                         }
70                         // any reference reported at this level is removed from the parent
71                         // context
72                         // where it could also be reported again
73                         if (complained) {
74                                 FlowContext currentContext = parent;
75                                 while (currentContext != null) {
76                                         // if (currentContext.isSubRoutine()) {
77                                         currentContext
78                                                         .removeFinalAssignmentIfAny(finalAssignments[i]);
79                                         // }
80                                         currentContext = currentContext.parent;
81                                 }
82                         }
83                 }
84         }
85
86         public String individualToString() {
87
88                 StringBuffer buffer = new StringBuffer("Finally flow context"); //$NON-NLS-1$
89                 buffer
90                                 .append("[finalAssignments count -").append(assignCount).append(']'); //$NON-NLS-1$
91                 return buffer.toString();
92         }
93
94         public boolean isSubRoutine() {
95                 return true;
96         }
97
98         boolean recordFinalAssignment(VariableBinding binding,
99                         Reference finalAssignment) {
100                 if (assignCount == 0) {
101                         finalAssignments = new Reference[5];
102                         finalVariables = new VariableBinding[5];
103                 } else {
104                         if (assignCount == finalAssignments.length)
105                                 System.arraycopy(finalAssignments, 0,
106                                                 (finalAssignments = new Reference[assignCount * 2]), 0,
107                                                 assignCount);
108                         System.arraycopy(finalVariables, 0,
109                                         (finalVariables = new VariableBinding[assignCount * 2]), 0,
110                                         assignCount);
111                 }
112                 ;
113                 finalAssignments[assignCount] = finalAssignment;
114                 finalVariables[assignCount++] = binding;
115                 return true;
116         }
117
118         void removeFinalAssignmentIfAny(Reference reference) {
119                 for (int i = 0; i < assignCount; i++) {
120                         if (finalAssignments[i] == reference) {
121                                 finalAssignments[i] = null;
122                                 finalVariables[i] = null;
123                                 return;
124                         }
125                 }
126         }
127 }