EMMA Coverage Report (generated Sat Dec 08 18:13:49 GMT 2007)
[all classes][uk.co.zonetora.fj.typecheck]

COVERAGE SUMMARY FOR SOURCE FILE [ClassTable.java]

nameclass, %method, %block, %line, %
ClassTable.java100% (1/1)92%  (11/12)87%  (296/340)94%  (66.7/71)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ClassTable100% (1/1)92%  (11/12)87%  (296/340)94%  (66.7/71)
lookupField (FieldName, ClassName): ClassName 0%   (0/1)0%   (0/8)0%   (0/1)
getSuperClassName (ClassName): ClassName 100% (1/1)48%  (12/25)67%  (2/3)
addClassDefinition (ClassDecl): void 100% (1/1)67%  (24/36)86%  (6/7)
checkAllClassNamesUsedAreDefined (): List 100% (1/1)82%  (51/62)87%  (8.7/10)
<static initializer> 100% (1/1)100% (6/6)100% (2/2)
ClassTable (): void 100% (1/1)100% (8/8)100% (3/3)
checkCOK (): List 100% (1/1)100% (25/25)100% (4/4)
checkForCycles (): List 100% (1/1)100% (57/57)100% (12/12)
fields (ClassName): List 100% (1/1)100% (34/34)100% (9/9)
mType (MethodName, ClassName): Maybe 100% (1/1)100% (19/19)100% (4/4)
subtype (ClassName, ClassName): boolean 100% (1/1)100% (29/29)100% (8/8)
validateClassTable (): void 100% (1/1)100% (31/31)100% (8/8)

1package uk.co.zonetora.fj.typecheck;
2 
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.HashMap;
6import java.util.HashSet;
7import java.util.List;
8import java.util.Map;
9import java.util.Set;
10 
11import uk.co.zonetora.fj.model.ClassDecl;
12import uk.co.zonetora.fj.model.ClassName;
13import uk.co.zonetora.fj.model.FieldName;
14import uk.co.zonetora.fj.model.Method;
15import uk.co.zonetora.fj.model.MethodName;
16import uk.co.zonetora.fj.passes.FJException;
17import uk.co.zonetora.fj.util.Maybe;
18import uk.co.zonetora.fj.util.Nothing;
19import uk.co.zonetora.fj.util.Tuple;
20 
21public class ClassTable {
22 
23        private static final ClassName objectClassName = new ClassName("Object");
24 
25    
26        private final Map<ClassName, ClassDecl> classTable;
27        
28        public ClassTable() {
29                this.classTable = new HashMap<ClassName,ClassDecl>();
30        }
31        
32        public void addClassDefinition(ClassDecl decl) throws FJException {
33                ClassName name = decl.getClassName();
34                
35                if(this.classTable.containsKey(name)) {
36                        throw new FJException("Duplicate definition for class: " + name.getClassName());
37                }
38                
39                if(name.equals(objectClassName)) {
40                        throw new FJException("Trying to define class Object");
41                }
42                
43        this.classTable.put(name, decl);
44        }
45 
46        public void validateClassTable() throws FJException {
47                List<FJException> exceptions = new ArrayList<FJException>();
48                
49                exceptions.addAll(checkForCycles());
50                exceptions.addAll(checkAllClassNamesUsedAreDefined());
51                
52                if(exceptions.isEmpty()) {
53                        exceptions.addAll(checkCOK());
54                }
55 
56                if(!exceptions.isEmpty()) {
57                        throw new FJExceptions(exceptions);
58                }
59        }
60        
61        private List<FJException> checkCOK() {
62                List<FJException> exceptions = new ArrayList<FJException>();
63                
64                for(ClassDecl decl : this.classTable.values()) {
65                        exceptions.addAll(decl.checkCOK(this));
66                }
67                
68                return exceptions;
69        }
70 
71        private List<FJException> checkAllClassNamesUsedAreDefined() {
72                List<FJException> exceptions = new ArrayList<FJException>();
73                Set<ClassName> referencedNames = new HashSet<ClassName>();
74                for(ClassDecl value : this.classTable.values()) {
75                        referencedNames.addAll(value.getAllReferencedClassNames());
76                }
77                
78                referencedNames.remove(objectClassName);
79                
80                Set<ClassName> knowns = new HashSet<ClassName>(this.classTable.keySet());
81                referencedNames.removeAll(knowns);
82                for(ClassName c : referencedNames) {
83                        exceptions.add(new FJUnknownClassNameException(c));
84                }
85                return exceptions;
86        }
87 
88        private List<FJException> checkForCycles() throws FJException {
89                final List<FJException> exceptions = new ArrayList<FJException>();
90                
91                final Set<ClassName> safeClasses = new HashSet<ClassName>();
92                
93                outer: for(ClassName c : this.classTable.keySet()) {
94                        if(safeClasses.contains(c)) { continue; }
95                        
96                        Set<ClassName> path = new HashSet<ClassName>();
97                        
98                        while(path.add(c)) {
99                                c = getSuperClassName(c);
100                                if(c.equals(ClassTable.objectClassName)) {
101                                        safeClasses.addAll(path);
102                                        continue outer;
103                                }
104                        }
105                        exceptions.add(new FJPathCycleException(path));
106                }
107                
108                
109                return exceptions;
110        }
111 
112        private ClassName getSuperClassName(ClassName c) throws FJException {
113                if(!this.classTable.containsKey(c)) {
114                        throw new FJException("ClassName: " + c + "  does not exist in classtable");
115                } else {
116                        return this.classTable.get(c).getSuperClass();
117                }
118        }
119 
120        @SuppressWarnings("unchecked")
121    public List<Tuple<ClassName, FieldName>> fields(ClassName className) {
122                if(className.equals(objectClassName)) {
123                        return Collections.EMPTY_LIST;
124                }
125                
126                ClassDecl c = this.classTable.get(className);
127                List<Tuple<ClassName, FieldName>> cFields = c.getFields();
128                List<Tuple<ClassName, FieldName>> superFields = fields(c.getSuperClass());
129                
130                List<Tuple<ClassName, FieldName>> allFields = new ArrayList<Tuple<ClassName, FieldName>>();
131                
132                allFields.addAll(cFields);
133                allFields.addAll(superFields);
134                
135                return allFields;
136        }
137    
138    public Maybe<Method> mType(MethodName mn, ClassName cn) {
139        if(cn.equals(ClassTable.objectClassName)) {
140            return new Nothing<Method>();
141        }
142        
143        ClassDecl c = this.classTable.get(cn);
144        
145        return c.lookupMethod(mn, this);
146    }
147 
148    /**
149     * is codeType <: returnType
150     */
151    public boolean subtype(ClassName codeType, ClassName returnType) {
152            if(codeType.equals(returnType)) {
153                    return true;
154            }
155            
156            ClassDecl codeDecl = this.classTable.get(codeType);
157            if(codeDecl != null) {
158                    if(codeDecl.getSuperClass().equals(returnType)) {
159                            return true;
160                    }
161                    return (subtype(codeDecl.getSuperClass(), returnType));
162            }
163            
164            return false;
165            
166    }
167 
168    public ClassName lookupField(FieldName fieldName, ClassName pathType) throws FJException {
169        return this.classTable.get(pathType).getFieldType(fieldName);
170    }
171}

[all classes][uk.co.zonetora.fj.typecheck]
EMMA 2.0.5312 (C) Vladimir Roubtsov