A variable description (like PHPFunctionDeclaration)
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / flow / FinallyFlowContext.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.lookup.BindingIds;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding;
20
21 /**
22  * Reflects the context of code analysis, keeping track of enclosing
23  *      try statements, exception handlers, etc...
24  */
25 public class FinallyFlowContext extends FlowContext {
26         
27         Reference finalAssignments[];
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                         Reference ref;
44                         if (((ref = finalAssignments[i]).bits & BindingIds.FIELD) != 0) {
45                                 // final field
46                                 if (flowInfo.isPotentiallyAssigned(ref.fieldBinding())) {
47                                         scope.problemReporter().duplicateInitializationOfBlankFinalField(ref.fieldBinding(), ref);
48                                 }
49                         } else {
50                                 // final local variable
51                                 if (flowInfo
52                                         .isPotentiallyAssigned((LocalVariableBinding) ((NameReference) ref).binding)) {
53                                         scope.problemReporter().duplicateInitializationOfFinalLocal(
54                                                 (LocalVariableBinding) ((NameReference) ref).binding,
55                                                 (NameReference) ref);
56                                 }
57                         }
58                         // any reference reported at this level is removed from the parent context 
59                         // where it could also be reported again
60                         FlowContext currentContext = parent;
61                         while (currentContext != null) {
62                                 if (currentContext.isSubRoutine()) {
63                                         currentContext.removeFinalAssignmentIfAny(ref);
64                                 }
65                                 currentContext = currentContext.parent;
66                         }
67                 }
68         }
69
70         public boolean isSubRoutine() {
71                 return true;
72         }
73
74         boolean recordFinalAssignment(
75                 VariableBinding binding,
76                 Reference finalAssignment) {
77                 if (assignCount == 0) {
78                         finalAssignments = new Reference[5];
79                 } else {
80                         if (assignCount == finalAssignments.length)
81                                 System.arraycopy(
82                                         finalAssignments,
83                                         0,
84                                         (finalAssignments = new Reference[assignCount * 2]),
85                                         0,
86                                         assignCount);
87                 };
88                 finalAssignments[assignCount++] = finalAssignment;
89                 return true;
90         }
91 }