mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-03-14 11:50:28 +08:00
fix compile time check for private member access
This commit is contained in:
parent
39c788cd02
commit
ab8a0b32e5
@ -6,7 +6,16 @@ package com.alibaba.testable.processor.exception;
|
||||
public class MemberNotExistException extends RuntimeException {
|
||||
|
||||
public MemberNotExistException(String type, String className, String target) {
|
||||
super(type + " \"" + target + "\" not exist in class \"" + className + "\"");
|
||||
super(String.format("%s \"%s\" not exist in class \"%s\"", type, target, className));
|
||||
}
|
||||
|
||||
public MemberNotExistException(String type, String className, String target, int count) {
|
||||
super(String.format("%s \"%s\" with %d %s not exist in class \"%s\"",
|
||||
type, target, count, parameters(count), className));
|
||||
}
|
||||
|
||||
private static String parameters(int count) {
|
||||
return count > 1 ? "parameters" : "parameter";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -146,13 +146,13 @@ public class EnablePrivateAccessTranslator extends BaseTranslator {
|
||||
// check is invoking a private method of source class
|
||||
if (expr instanceof JCMethodInvocation) {
|
||||
JCMethodInvocation invocation = (JCMethodInvocation)expr;
|
||||
privateAccessChecker.validate(invocation);
|
||||
MemberType memberType = checkInvokeType(invocation);
|
||||
if (memberType.equals(MemberType.PRIVATE_OR_FINAL)) {
|
||||
expr = privateAccessStatementGenerator.fetchInvokeStatement(invocation);
|
||||
} else if (memberType.equals(MemberType.STATIC_PRIVATE)) {
|
||||
expr = privateAccessStatementGenerator.fetchStaticInvokeStatement(invocation);
|
||||
}
|
||||
privateAccessChecker.validate((JCMethodInvocation)expr);
|
||||
}
|
||||
// check the casted expression
|
||||
if (expr instanceof JCTypeCast) {
|
||||
|
@ -17,6 +17,7 @@ import java.util.Map;
|
||||
public class PrivateAccessChecker {
|
||||
|
||||
private static final String CLASS_NAME_PRIVATE_ACCESSOR = "PrivateAccessor";
|
||||
private static final String CLASS_NAME_PRIVATE_ACCESSOR_FULL = "com.alibaba.testable.core.accessor.PrivateAccessor";
|
||||
private static final List<String> FIELD_ACCESS_METHOD = Arrays.asList(new String[]
|
||||
{ "get", "set", "getStatic", "setStatic" }.clone());
|
||||
private static final List<String> FIELD_INVOKE_METHOD = Arrays.asList(new String[]
|
||||
@ -37,8 +38,7 @@ public class PrivateAccessChecker {
|
||||
public void validate(JCTree.JCMethodInvocation invocation) {
|
||||
if (invocation.meth instanceof JCTree.JCFieldAccess && invocation.args.length() >= 2) {
|
||||
JCTree.JCFieldAccess fieldAccess = (JCTree.JCFieldAccess)invocation.meth;
|
||||
if (fieldAccess.selected instanceof JCTree.JCIdent && invocation.args.get(1) instanceof JCTree.JCLiteral &&
|
||||
((JCTree.JCIdent)fieldAccess.selected).name.toString().equals(CLASS_NAME_PRIVATE_ACCESSOR)) {
|
||||
if (invocation.args.get(1) instanceof JCTree.JCLiteral && isPrivateAccessor(fieldAccess)) {
|
||||
Object target = ((JCTree.JCLiteral)invocation.args.get(1)).getValue();
|
||||
if (target instanceof String) {
|
||||
String methodName = fieldAccess.name.toString();
|
||||
@ -55,10 +55,10 @@ public class PrivateAccessChecker {
|
||||
checkParameterCount(sourceMembers.privateMethods, (String)target, parameterCount)) {
|
||||
// Let it go
|
||||
} else if (sourceMembers.nonPrivateMethods.containsKey(target) &&
|
||||
checkParameterCount(sourceMembers.privateMethods, (String)target, parameterCount)) {
|
||||
checkParameterCount(sourceMembers.nonPrivateMethods, (String)target, parameterCount)) {
|
||||
cx.logger.warn("Method " + className + "::" + target + " is not private.");
|
||||
} else {
|
||||
throw new MemberNotExistException(TYPE_METHOD, className, (String)target);
|
||||
throw new MemberNotExistException(TYPE_METHOD, className, (String)target, parameterCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -66,6 +66,20 @@ public class PrivateAccessChecker {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPrivateAccessor(JCTree.JCFieldAccess fieldAccess) {
|
||||
return isPrivateAccessorWithShortRef(fieldAccess) || isPrivateAccessorWithFullRef(fieldAccess);
|
||||
}
|
||||
|
||||
private boolean isPrivateAccessorWithShortRef(JCTree.JCFieldAccess fieldAccess) {
|
||||
return fieldAccess.selected instanceof JCTree.JCIdent &&
|
||||
((JCTree.JCIdent)fieldAccess.selected).name.toString().equals(CLASS_NAME_PRIVATE_ACCESSOR);
|
||||
}
|
||||
|
||||
private boolean isPrivateAccessorWithFullRef(JCTree.JCFieldAccess fieldAccess) {
|
||||
return fieldAccess.selected instanceof JCTree.JCFieldAccess &&
|
||||
fieldAccess.selected.toString().equals(CLASS_NAME_PRIVATE_ACCESSOR_FULL);
|
||||
}
|
||||
|
||||
private boolean checkParameterCount(Map<String, List<Integer>> methods, String target, int parameterCount) {
|
||||
for (Integer expectCount : methods.get(target)) {
|
||||
if (countMatch(parameterCount, expectCount)) {
|
||||
|
@ -22,7 +22,8 @@ public class TestableLogger {
|
||||
}
|
||||
|
||||
public void warn(String msg) {
|
||||
messager.printMessage(Diagnostic.Kind.WARNING, msg);
|
||||
// Message level WARNING won't show, use MANDATORY_WARNING instead
|
||||
messager.printMessage(Diagnostic.Kind.MANDATORY_WARNING, msg);
|
||||
}
|
||||
|
||||
public void error(String msg) {
|
||||
|
Loading…
Reference in New Issue
Block a user