in android/src/org/jetbrains/android/inspections/VersionChecks.java [172:297]
private static Boolean isVersionCheckConditional(int api,
@NotNull PsiElement element, boolean and, @Nullable PsiElement prev,
@Nullable ApiLevelLookup apiLookup) {
if (element instanceof PsiPolyadicExpression) {
if (element instanceof PsiBinaryExpression) {
Boolean ok = isVersionCheckConditional(api, and, (PsiBinaryExpression)element,
apiLookup);
if (ok != null) {
return ok;
}
}
PsiPolyadicExpression expression = (PsiPolyadicExpression)element;
IElementType tokenType = expression.getOperationTokenType();
if (and && tokenType == JavaTokenType.ANDAND) {
if (isAndedWithConditional(element, api, prev)) {
return true;
}
}
else if (!and && tokenType == JavaTokenType.OROR) {
if (isOredWithConditional(element, api, prev)) {
return true;
}
}
}
else if (element instanceof PsiMethodCallExpression) {
PsiMethodCallExpression call = (PsiMethodCallExpression)element;
PsiMethod method = call.resolveMethod();
if (method == null) {
return null;
}
String name = method.getName();
if (name.startsWith("isAtLeast")) {
PsiClass containingClass = method.getContainingClass();
if (containingClass != null && "android.support.v4.os.BuildCompat".equals(
containingClass.getQualifiedName())) {
if (name.equals("isAtLeastN")) {
return api <= 24;
}
else if (name.equals("isAtLeastNMR1")) {
return api <= 25;
}
}
}
PsiCodeBlock body = method.getBody();
if (body == null) {
return null;
}
PsiStatement[] statements = body.getStatements();
if (statements.length != 1) {
return null;
}
PsiStatement statement = statements[0];
if (!(statement instanceof PsiReturnStatement)) {
return null;
}
PsiReturnStatement returnStatement = (PsiReturnStatement)statement;
PsiExpression returnValue = returnStatement.getReturnValue();
if (returnValue == null) {
return null;
}
PsiExpression[] expressions = call.getArgumentList().getExpressions();
if (expressions.length == 0) {
Boolean ok = isVersionCheckConditional(api, returnValue, and,
null, null);
if (ok != null) {
return ok;
}
}
if (expressions.length == 1) {
// See if we're passing in a value
ApiLevelLookup lookup = arg -> {
if (arg instanceof PsiReferenceExpression) {
PsiElement resolved = ((PsiReferenceExpression)arg).resolve();
if (resolved instanceof PsiParameter) {
PsiParameter parameter = (PsiParameter)resolved;
PsiParameterList parameterList = PsiTreeUtil.getParentOfType(resolved,
PsiParameterList.class);
if (parameterList != null) {
int index = parameterList.getParameterIndex(parameter);
if (index != -1 && index < expressions.length) {
return getApiLevel(expressions[index], null);
}
}
}
}
return -1;
};
Boolean ok = isVersionCheckConditional(api, returnValue, and, null, lookup);
if (ok != null) {
return ok;
}
}
}
else if (element instanceof PsiReferenceExpression) {
// Constant expression for an SDK version check?
PsiReferenceExpression refExpression = (PsiReferenceExpression)element;
PsiElement resolved = refExpression.resolve();
if (resolved instanceof PsiField) {
PsiField field = (PsiField)resolved;
PsiModifierList modifierList = field.getModifierList();
if (modifierList != null && modifierList.hasExplicitModifier(PsiModifier.STATIC)) {
PsiExpression initializer = field.getInitializer();
if (initializer != null) {
Boolean ok = isVersionCheckConditional(api, initializer, and, null, null);
if (ok != null) {
return ok;
}
}
}
}
}
else if (element instanceof PsiPrefixExpression) {
PsiPrefixExpression prefixExpression = (PsiPrefixExpression)element;
if (prefixExpression.getOperationTokenType() == JavaTokenType.EXCL) {
PsiExpression operand = prefixExpression.getOperand();
if (operand != null) {
Boolean ok = isVersionCheckConditional(api, operand, !and, null, null);
if (ok != null) {
return ok;
}
}
}
}
return null;
}