All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.siyeh.ig.internationalization.NonNlsUtils Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition java-analysis-impl library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2007-2010 Bas Leijdekkers
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.siyeh.ig.internationalization;

import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.Nullable;

public class NonNlsUtils {

  private static final Key KEY = new Key("IG_NON_NLS_ANNOTATED_USE");

  private NonNlsUtils() {
  }

  @Nullable
  public static PsiModifierListOwner getAnnotatableArgument(
    PsiMethodCallExpression methodCallExpression) {
    final PsiExpressionList argumentList =
      methodCallExpression.getArgumentList();
    final PsiExpression[] arguments = argumentList.getExpressions();
    if (arguments.length < 1) {
      return null;
    }
    final PsiExpression argument = arguments[0];
    if (argument instanceof PsiReferenceExpression) {
      final PsiReferenceExpression referenceExpression =
        (PsiReferenceExpression)argument;
      final PsiElement element = referenceExpression.resolve();
      if (element instanceof PsiModifierListOwner) {
        return (PsiModifierListOwner)element;
      }
    }
    return null;
  }

  @Nullable
  public static PsiModifierListOwner getAnnotatableQualifier(
    PsiReferenceExpression expression) {
    final PsiExpression qualifierExpression =
      expression.getQualifierExpression();
    if (qualifierExpression instanceof PsiReferenceExpression) {
      final PsiReferenceExpression referenceExpression =
        (PsiReferenceExpression)qualifierExpression;
      final PsiElement element = referenceExpression.resolve();
      if (element instanceof PsiModifierListOwner) {
        return (PsiModifierListOwner)element;
      }
    }
    return null;
  }

  public static boolean isNonNlsAnnotated(
    @Nullable PsiExpression expression) {
    if (isReferenceToNonNlsAnnotatedElement(expression)) {
      return true;
    }
    if (expression instanceof PsiMethodCallExpression) {
      final PsiMethodCallExpression methodCallExpression =
        (PsiMethodCallExpression)expression;
      final PsiMethod method = methodCallExpression.resolveMethod();
      if (isNonNlsAnnotatedModifierListOwner(method)) {
        return true;
      }
      final PsiReferenceExpression methodExpression =
        methodCallExpression.getMethodExpression();
      final PsiExpression qualifier =
        methodExpression.getQualifierExpression();
      return isNonNlsAnnotated(qualifier);
    }
    else if (expression instanceof PsiArrayAccessExpression) {
      final PsiArrayAccessExpression arrayAccessExpression =
        (PsiArrayAccessExpression)expression;
      final PsiExpression arrayExpression =
        arrayAccessExpression.getArrayExpression();
      return isNonNlsAnnotated(arrayExpression);
    }
    return false;
  }

  public static boolean isNonNlsAnnotatedUse(
    @Nullable PsiExpression expression) {
    if (expression == null) {
      return false;
    }
    final Boolean value = getCachedValue(expression, KEY);
    if (value != null) {
      return value.booleanValue();
    }
    final PsiElement element =
      PsiTreeUtil.getParentOfType(expression,
                                  PsiExpressionList.class,
                                  PsiAssignmentExpression.class,
                                  PsiVariable.class,
                                  PsiReturnStatement.class);
    final boolean result;
    if (element instanceof PsiExpressionList) {
      final PsiExpressionList expressionList =
        (PsiExpressionList)element;
      result = isNonNlsAnnotatedParameter(expression, expressionList);
    }
    else if (element instanceof PsiVariable) {
      result = isNonNlsAnnotatedModifierListOwner(element);
    }
    else if (element instanceof PsiAssignmentExpression) {
      final PsiAssignmentExpression assignmentExpression =
        (PsiAssignmentExpression)element;
      result =
        isAssignmentToNonNlsAnnotatedVariable(assignmentExpression);
    }
    else if (element instanceof PsiReturnStatement) {
      final PsiMethod method =
        PsiTreeUtil.getParentOfType(element, PsiMethod.class);
      result = isNonNlsAnnotatedModifierListOwner(method);
    }
    else {
      result = false;
    }
    putCachedValue(expression, KEY, Boolean.valueOf(result));
    return result;
  }

  private static  void putCachedValue(PsiExpression expression,
                                         Key key, T value) {
    if (expression instanceof PsiBinaryExpression) {
      expression.putUserData(key, value);
    }
  }

  @Nullable
  private static  T getCachedValue(PsiExpression expression, Key key) {
    final T data = expression.getUserData(key);
    if (!(expression instanceof PsiBinaryExpression)) {
      return data;
    }
    final PsiBinaryExpression binaryExpression =
      (PsiBinaryExpression)expression;
    final PsiExpression lhs = binaryExpression.getLOperand();
    T childData = null;
    if (lhs instanceof PsiBinaryExpression) {
      childData = lhs.getUserData(key);
    }
    if (childData == null) {
      final PsiExpression rhs = binaryExpression.getROperand();
      if (rhs instanceof PsiBinaryExpression) {
        childData = rhs.getUserData(key);
      }
    }
    if (childData != data) {
      expression.putUserData(key, childData);
    }
    return childData;
  }

  private static boolean isAssignmentToNonNlsAnnotatedVariable(
    PsiAssignmentExpression assignmentExpression) {
    final PsiExpression lhs = assignmentExpression.getLExpression();
    return isReferenceToNonNlsAnnotatedElement(lhs);
  }

  private static boolean isReferenceToNonNlsAnnotatedElement(
    @Nullable PsiExpression expression) {
    if (!(expression instanceof PsiReferenceExpression)) {
      return false;
    }
    final PsiReferenceExpression referenceExpression =
      (PsiReferenceExpression)expression;
    final PsiElement target = referenceExpression.resolve();
    return isNonNlsAnnotatedModifierListOwner(target);
  }

  private static boolean isNonNlsAnnotatedParameter(
    PsiExpression expression,
    PsiExpressionList expressionList) {
    final PsiElement parent = expressionList.getParent();
    final PsiParameterList parameterList;
    if (parent instanceof PsiMethodCallExpression) {
      final PsiMethodCallExpression methodCallExpression =
        (PsiMethodCallExpression)parent;
      if (isQualifierNonNlsAnnotated(methodCallExpression)) {
        return true;
      }
      final PsiMethod method = methodCallExpression.resolveMethod();
      if (method == null) {
        return false;
      }
      parameterList = method.getParameterList();
    }
    else if (parent instanceof PsiNewExpression) {
      final PsiNewExpression newExpression = (PsiNewExpression)parent;
      final PsiMethod constructor = newExpression.resolveConstructor();
      if (constructor == null) {
        return false;
      }
      parameterList = constructor.getParameterList();
    }
    else {
      return false;
    }
    final PsiExpression[] expressions = expressionList.getExpressions();
    int index = -1;
    for (int i = 0; i < expressions.length; i++) {
      final PsiExpression argument = expressions[i];
      if (PsiTreeUtil.isAncestor(argument, expression, false)) {
        index = i;
      }
    }
    final PsiParameter[] parameters = parameterList.getParameters();
    if (parameters.length == 0) {
      return false;
    }
    final PsiParameter parameter;
    if (index < parameters.length) {
      parameter = parameters[index];
    }
    else {
      parameter = parameters[parameters.length - 1];
    }
    return isNonNlsAnnotatedModifierListOwner(parameter);
  }

  private static boolean isQualifierNonNlsAnnotated(
    PsiMethodCallExpression methodCallExpression) {
    final PsiReferenceExpression methodExpression =
      methodCallExpression.getMethodExpression();
    final PsiExpression qualifier =
      methodExpression.getQualifierExpression();
    if (isReferenceToNonNlsAnnotatedElement(qualifier)) {
      return true;
    }
    if (qualifier instanceof PsiMethodCallExpression) {
      final PsiMethod method = methodCallExpression.resolveMethod();
      if (method == null) {
        return false;
      }
      if (isChainable(method)) {
        final PsiMethodCallExpression expression =
          (PsiMethodCallExpression)qualifier;
        if (isQualifierNonNlsAnnotated(expression)) {
          return true;
        }
      }
    }
    return false;
  }

  private static boolean isChainable(PsiMethod method) {
    if (method == null) {
      return false;
    }
    method = (PsiMethod)method.getNavigationElement();
    final PsiCodeBlock body = method.getBody();
    if (body == null) {
      return false;
    }
    final PsiStatement[] statements = body.getStatements();
    if (statements.length == 0) {
      return false;
    }
    final PsiStatement lastStatement = statements[statements.length - 1];
    if (!(lastStatement instanceof PsiReturnStatement)) {
      return false;
    }
    final PsiReturnStatement returnStatement =
      (PsiReturnStatement)lastStatement;
    final PsiExpression returnValue = returnStatement.getReturnValue();
    return returnValue instanceof PsiThisExpression;
  }

  private static boolean isNonNlsAnnotatedModifierListOwner(
    @Nullable PsiElement element) {
    if (!(element instanceof PsiModifierListOwner)) {
      return false;
    }
    final PsiModifierListOwner variable = (PsiModifierListOwner)element;
    return AnnotationUtil.isAnnotated(variable,
                                      AnnotationUtil.NON_NLS, false, false);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy