[go: nahoru, domu]

Skip to content

Commit

Permalink
add first prototype of binary operators setting system
Browse files Browse the repository at this point in the history
  • Loading branch information
zhvkgj committed Apr 16, 2020
1 parent 2792933 commit 4abf643
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 38 deletions.
3 changes: 3 additions & 0 deletions examples/src/main/java/examples/Dollar.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
package examples;

import annvisitor.util.PermissionPolicy;

public class Dollar {
public static final PermissionPolicy PLUS = PermissionPolicy.FORBID;
}
1 change: 1 addition & 0 deletions examples/src/main/java/examples/SubEuro.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package examples;

public class SubEuro extends Euro {

}
29 changes: 29 additions & 0 deletions subtyping-annotation-processor/src/main/java/ann/type/Top.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,33 @@
package ann.type;

import annvisitor.util.PermissionPolicy;

public class Top {
public static final PermissionPolicy PLUS = PermissionPolicy.ALLOW;
public static final PermissionPolicy MINUS = PermissionPolicy.ALLOW;
public static final PermissionPolicy MULTIPLY = PermissionPolicy.ALLOW;
public static final PermissionPolicy DIVIDE = PermissionPolicy.ALLOW;
public static final PermissionPolicy REMAINDER = PermissionPolicy.ALLOW;

public static final PermissionPolicy AND = PermissionPolicy.ALLOW;
public static final PermissionPolicy OR = PermissionPolicy.ALLOW;
public static final PermissionPolicy XOR = PermissionPolicy.ALLOW;

public static final PermissionPolicy CONDITIONAL_AND = PermissionPolicy.ALLOW;
public static final PermissionPolicy CONDITIONAL_OR = PermissionPolicy.ALLOW;

public static final PermissionPolicy LEFT_SHIFT = PermissionPolicy.ALLOW;
public static final PermissionPolicy RIGHT_SHIFT = PermissionPolicy.ALLOW;
public static final PermissionPolicy UNSIGNED_RIGHT_SHIFT = PermissionPolicy.ALLOW;

public static final PermissionPolicy EQUALS = PermissionPolicy.ALLOW;

public static final PermissionPolicy UNARY_PLUS = PermissionPolicy.ALLOW;
public static final PermissionPolicy UNARY_MINUS = PermissionPolicy.ALLOW;

public static final PermissionPolicy INCREMENT = PermissionPolicy.ALLOW;
public static final PermissionPolicy DECREMENT = PermissionPolicy.ALLOW;

public static final PermissionPolicy LOGICAL_COMPLEMENT = PermissionPolicy.ALLOW;
public static final PermissionPolicy BITWISE_COMPLEMENT = PermissionPolicy.ALLOW;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,52 @@

import ann.Type;
import ann.type.Top;
import annvisitor.util.PermissionPolicy;
import annvisitor.util.ResultKind;

import static annvisitor.util.AnnotationValueSubtypes.*;
import static annvisitor.util.Messager.printResultInfo;

import com.sun.source.tree.*;
import com.sun.source.util.TreePath;
import com.sun.source.util.TreeScanner;
import com.sun.source.util.Trees;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.MirroredTypeException;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import java.util.*;
import java.util.stream.Collectors;

// first String for inferred type, second String for type checks of return expression
public class AnnotationValueTypeTreeScanner extends TreeScanner<String, String> {
private final ProcessingEnvironment processingEnv;
private final Trees mTrees;

private static class AnnTreeScanHolder {
private static final AnnotationValueTypeTreeScanner HOLDER_INSTANCE = new AnnotationValueTypeTreeScanner();
}

private ProcessingEnvironment processingEnv;
private Trees mTrees;
private CompilationUnitTree cut;
private Map<Element, String> localVarsTypes;

Map<Element, String> localVarsTypes = new HashMap<>();
private AnnotationValueTypeTreeScanner() {

public AnnotationValueTypeTreeScanner(ProcessingEnvironment processingEnv, CompilationUnitTree cut) {
this.processingEnv = processingEnv;
this.mTrees = Trees.instance(processingEnv);
this.cut = cut;
}

public static AnnotationValueTypeTreeScanner getInstance(ProcessingEnvironment processingEnv,
CompilationUnitTree cut) {
AnnTreeScanHolder.HOLDER_INSTANCE.processingEnv = processingEnv;
AnnTreeScanHolder.HOLDER_INSTANCE.mTrees = Trees.instance(processingEnv);
AnnTreeScanHolder.HOLDER_INSTANCE.cut = cut;
AnnTreeScanHolder.HOLDER_INSTANCE.localVarsTypes = new HashMap<>();
return AnnTreeScanHolder.HOLDER_INSTANCE;
}

private ResultKind checkParamsMatching(List<? extends ExpressionTree> actParams,
Expand Down Expand Up @@ -82,6 +98,68 @@ private ResultKind checkParamsMatching(List<? extends ExpressionTree> actParams,
return ResultKind.OK;
}

private String treeKindToFieldName(Tree.Kind op) {
switch (op) {
case POSTFIX_DECREMENT:
case PREFIX_DECREMENT:
return "DECREMENT";
case POSTFIX_INCREMENT:
case PREFIX_INCREMENT:
return "INCREMENT";
case EQUAL_TO:
case NOT_EQUAL_TO:
case GREATER_THAN_EQUAL:
case LESS_THAN_EQUAL:
case LESS_THAN:
case GREATER_THAN:
return "EQUALS";
default:
return op.toString();
}
}

private PermissionPolicy isOperationAllow(Tree.Kind op, String type) {
LinkedList<String> path = new LinkedList<>();
PermissionPolicy result = PermissionPolicy.ALLOW;

if (findPath(type, Top.class.getName(), path, processingEnv)) {
String fieldName = treeKindToFieldName(op);
for (String type1 : path) {
if (!type1.contentEquals(Top.class.getName())) {
TypeElement clazz = processingEnv.getElementUtils().getTypeElement(type1);
List<VariableElement> fields = ElementFilter
.fieldsIn(clazz.getEnclosedElements())
.stream()
.filter(ve -> ve.getSimpleName().contentEquals(fieldName))
.collect(Collectors.toList());
VariableTree field = fields.isEmpty() ? null : (VariableTree) mTrees.getTree(fields.get(0));
if (field != null) {
ExpressionTree init = field.getInitializer();
if (init != null && init.getKind() == Tree.Kind.MEMBER_SELECT) {
// todo: implement correctly
String value = ((MemberSelectTree) init).getIdentifier().toString();
switch (value) {
case "ALLOW":
result = PermissionPolicy.ALLOW;
break;
case "ALLOW_WITH_WARNING":
result = PermissionPolicy.ALLOW_WITH_WARNING;
break;
case "FORBID":
result = PermissionPolicy.FORBID;
break;
}
} else {
printResultInfo(field, ResultKind.MISSING_PERMISSION_VALUE, mTrees, cut);
}
}
}
}
}

return result;
}

@Override
public String visitMethod(MethodTree node, String aVoid) {
// node is a constructor
Expand Down Expand Up @@ -233,40 +311,46 @@ public String visitCompoundAssignment(CompoundAssignmentTree node, String aVoid)
String var = scan(node.getVariable(), aVoid);
String expr = scan(node.getExpression(), aVoid);
Tree.Kind op = node.getKind();
switch (op) {
case PLUS_ASSIGNMENT:
case MINUS_ASSIGNMENT:
if (!expr.equals(Top.class.getName()) && !isSubtype(expr, var, processingEnv)) {
printResultInfo(node, ResultKind.INCORRECT_VARIABLE_TYPE, mTrees, cut);
}
break;
default:
printResultInfo(node, ResultKind.WRONG_APPLY_OPERATOR, mTrees, cut);
if (!expr.equals(Top.class.getName()) && !isSubtype(expr, var, processingEnv)) {
printResultInfo(node, ResultKind.INCORRECT_VARIABLE_TYPE, mTrees, cut);
}
PermissionPolicy resOnVar = isOperationAllow(op, var);
PermissionPolicy resOnExpr = isOperationAllow(op, expr);
if (resOnVar != PermissionPolicy.ALLOW) {
printResultInfo(node, ResultKind.WRONG_APPLY_OPERATOR , mTrees, cut);
}
if (resOnExpr != PermissionPolicy.ALLOW) {
printResultInfo(node, ResultKind.WRONG_APPLY_OPERATOR, mTrees, cut);
}
return var;
}

@Override
public String visitUnary(UnaryTree node, String aVoid) {
String type = this.scan(node.getExpression(), aVoid);
Tree.Kind op = node.getKind();
PermissionPolicy resOnExpr = isOperationAllow(op, type);
if (resOnExpr != PermissionPolicy.ALLOW) {
printResultInfo(node, ResultKind.WRONG_APPLY_OPERATOR, mTrees, cut);
}
return type;
}

@Override
public String visitBinary(BinaryTree node, String aVoid) {
String l = this.scan(node.getLeftOperand(), aVoid);
String r = this.scan(node.getRightOperand(), aVoid);
Tree.Kind op = node.getKind();
switch (op) {
case LESS_THAN:
case LESS_THAN_EQUAL:
case GREATER_THAN:
case GREATER_THAN_EQUAL:
case EQUAL_TO:
case NOT_EQUAL_TO:
case PLUS:
case MINUS:
if (!isSubtype(l, r, processingEnv) && !isSubtype(r, l, processingEnv)) {
printResultInfo(node, ResultKind.TYPE_MISMATCH_OPERAND, mTrees, cut);
}
break;
default:
printResultInfo(node, ResultKind.WRONG_APPLY_OPERATOR, mTrees, cut);

if (!isSubtype(l, r, processingEnv) && !isSubtype(r, l, processingEnv)) {
printResultInfo(node, ResultKind.TYPE_MISMATCH_OPERAND, mTrees, cut);
}
PermissionPolicy resOnL = isOperationAllow(op, l);
PermissionPolicy resOnR = isOperationAllow(op, r);
if (resOnL != PermissionPolicy.ALLOW) {
printResultInfo(node, ResultKind.WRONG_APPLY_OPERATOR, mTrees, cut);
}
if (resOnR != PermissionPolicy.ALLOW) {
printResultInfo(node, ResultKind.WRONG_APPLY_OPERATOR, mTrees, cut);
}
return generalizeTypes(l, r, processingEnv);
}
Expand Down Expand Up @@ -295,7 +379,6 @@ public String visitMemberSelect(MemberSelectTree node, String aVoid) {
return type;
}


@Override
public String visitLiteral(LiteralTree node, String aVoid) {
return Top.class.getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@
import javax.lang.model.util.ElementScanner7;

public class ExecutableVisitor extends ElementScanner7<Void, Void> {
private final ProcessingEnvironment processingEnvironment;
private final Trees mTrees;
private final ProcessingEnvironment processingEnv;

public ExecutableVisitor(ProcessingEnvironment processingEnvironment) {
this.processingEnvironment = processingEnvironment;
this.mTrees = Trees.instance(processingEnvironment);
this.processingEnv = processingEnvironment;
}

@Override
public Void visitExecutable(ExecutableElement e, Void aVoid) {
AnnotationValueTypeTreeScanner subtypeTreeScan = new AnnotationValueTypeTreeScanner(processingEnv,
mTrees.getPath(e).getCompilationUnit());
subtypeTreeScan.scan(mTrees.getTree(e), null);
AnnotationValueTypeTreeScanner
.getInstance(processingEnvironment, mTrees.getPath(e).getCompilationUnit())
.scan(mTrees.getTree(e), null);
return super.visitExecutable(e, aVoid);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package annvisitor.util;

public enum PermissionPolicy {
ALLOW,
ALLOW_WITH_WARNING,
FORBID,
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ public enum ResultKind {
ANNOTATION_ON_VOID,
NON_ANNOTATED_PARAM,
MISSING_VALUE,
MISSING_PERMISSION_VALUE,
OK
}

0 comments on commit 4abf643

Please sign in to comment.