/** Check that the assignment to a field is correct. */ protected void checkFieldAssign( FlowGraph graph, FieldAssign a, DataFlowItem dfIn, DataFlowItem dfOut) throws SemanticException { Field f = (Field) a.left(); FieldInstance fi = f.fieldInstance(); if (fi.flags().isFinal()) { if ((currCBI.currCodeDecl instanceof ConstructorDecl || currCBI.currCodeDecl instanceof Initializer) && isFieldsTargetAppropriate(f)) { // we are in a constructor or initializer block and // if the field is static then the target is the class // at hand, and if it is not static then the // target of the field is this. // So a final field in this situation can be // assigned to at most once. MinMaxInitCount initCount = (MinMaxInitCount) dfOut.initStatus.get(fi); if (InitCount.MANY.equals(initCount.getMax())) { throw new SemanticException( "field \"" + fi.name() + "\" might already have been assigned to", a.position()); } } else { // not in a constructor or intializer, or the target is // not appropriate. So we cannot assign // to a final field at all. throw new SemanticException( "Cannot assign a value " + "to final field \"" + fi.name() + "\"", a.position()); } } }
/** Perform the appropriate flow operations for assignment to a field */ protected Map flowFieldAssign( DataFlowItem inItem, FlowGraph graph, FieldAssign a, Set succEdgeKeys) { Field f = (Field) a.left(); FieldInstance fi = f.fieldInstance(); if (fi.flags().isFinal() && isFieldsTargetAppropriate(f)) { // this field is final and the target for this field is // appropriate for what we are interested in. Map m = new HashMap(inItem.initStatus); MinMaxInitCount initCount = (MinMaxInitCount) m.get(fi); // initCount may be null if the field is defined in an // outer class. if (initCount != null) { initCount = new MinMaxInitCount(initCount.getMin().increment(), initCount.getMax().increment()); m.put(fi, initCount); return itemToMap(new DataFlowItem(m), succEdgeKeys); } } return null; }