-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy pathMethodsFirstChecker.java
More file actions
135 lines (125 loc) · 4.84 KB
/
MethodsFirstChecker.java
File metadata and controls
135 lines (125 loc) · 4.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package liquidjava.processor.refinement_checker;
import java.util.ArrayList;
import java.util.List;
import liquidjava.diagnostics.Diagnostics;
import liquidjava.diagnostics.errors.LJError;
import liquidjava.processor.context.Context;
import liquidjava.processor.refinement_checker.general_checkers.MethodsFunctionsChecker;
import liquidjava.rj_language.Predicate;
import liquidjava.utils.constants.Formats;
import liquidjava.utils.constants.Types;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtConstructor;
import spoon.reflect.declaration.CtEnum;
import spoon.reflect.declaration.CtEnumValue;
import spoon.reflect.declaration.CtInterface;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;
import spoon.reflect.factory.Factory;
import spoon.reflect.reference.CtTypeReference;
/** First visit to Spoon AST to get the method's refinements */
public class MethodsFirstChecker extends TypeChecker {
MethodsFunctionsChecker mfc;
List<String> visitedClasses;
Diagnostics diagnostics = Diagnostics.getInstance();
public MethodsFirstChecker(Context context, Factory factory) {
super(context, factory);
mfc = new MethodsFunctionsChecker(this);
visitedClasses = new ArrayList<>();
}
@Override
public <T> void visitCtClass(CtClass<T> ctClass) {
context.reinitializeContext();
if (visitedClasses.contains(ctClass.getQualifiedName()))
return;
else
visitedClasses.add(ctClass.getQualifiedName());
// visitInterfaces
if (!ctClass.getSuperInterfaces().isEmpty())
for (CtTypeReference<?> t : ctClass.getSuperInterfaces()) {
if (t.isInterface()) {
CtType<?> ct = t.getDeclaration();
if (ct instanceof CtInterface)
visitCtInterface((CtInterface<?>) ct);
}
}
// visitSubclasses
CtTypeReference<?> sup = ctClass.getSuperclass();
if (sup != null && sup.isClass()) {
CtType<?> ct = sup.getDeclaration();
if (ct instanceof CtClass)
visitCtClass((CtClass<?>) ct);
}
// first try-catch: process class-level annotations)
// errors here should not prevent visiting methods, constructors or fields of the class
try {
getRefinementFromAnnotation(ctClass);
handleStateSetsFromAnnotation(ctClass);
} catch (LJError e) {
diagnostics.add(e);
}
// second try-catch: visit class children (methods, constructors, fields)
// errors from one child should not prevent visiting sibling elements
try {
super.visitCtClass(ctClass);
} catch (LJError e) {
diagnostics.add(e);
}
}
@Override
public <T> void visitCtInterface(CtInterface<T> intrface) {
if (visitedClasses.contains(intrface.getQualifiedName()))
return;
else
visitedClasses.add(intrface.getQualifiedName());
if (getExternalRefinement(intrface).isPresent())
return;
// first try-catch: process interface-level annotations
// errors here should not prevent visiting the interface's methods
try {
getRefinementFromAnnotation(intrface);
handleStateSetsFromAnnotation(intrface);
} catch (LJError e) {
diagnostics.add(e);
}
// second try-catch: visit interface children (methods)
// errors from one child should not prevent visiting sibling methods
try {
super.visitCtInterface(intrface);
} catch (LJError e) {
diagnostics.add(e);
}
}
@Override
public <T> void visitCtConstructor(CtConstructor<T> c) {
context.enterContext();
try {
getRefinementFromAnnotation(c);
mfc.getConstructorRefinements(c);
super.visitCtConstructor(c);
} catch (LJError e) {
diagnostics.add(e);
}
context.exitContext();
}
public <R> void visitCtMethod(CtMethod<R> method) {
context.enterContext();
try {
mfc.getMethodRefinements(method);
super.visitCtMethod(method);
} catch (LJError e) {
diagnostics.add(e);
}
context.exitContext();
}
@Override
public <T extends Enum<?>> void visitCtEnum(CtEnum<T> enumRead) {
String enumName = enumRead.getSimpleName();
String qualifiedEnumName = enumRead.getQualifiedName();
for (CtEnumValue<?> ev : enumRead.getEnumValues()) {
String varName = String.format(Formats.ENUM, enumName, ev.getSimpleName());
context.addGlobalVariableToContext(varName, qualifiedEnumName, enumRead.getReference(), null);
}
super.visitCtEnum(enumRead);
}
}