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

com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil 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 2000-2014 JetBrains s.r.o.
 *
 * 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.intellij.codeInsight.daemon.impl.analysis;

import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;

public class JavaHighlightUtil {
  public static boolean isSerializable(@NotNull PsiClass aClass) {
    return isSerializable(aClass, "java.io.Serializable");
  }

  public static boolean isSerializable(@NotNull PsiClass aClass,
                                       String serializableClassName) {
    Project project = aClass.getManager().getProject();
    PsiClass serializableClass = JavaPsiFacade.getInstance(project).findClass(serializableClassName, aClass.getResolveScope());
    return serializableClass != null && aClass.isInheritor(serializableClass, true);
  }

  public static boolean isSerializationRelatedMethod(PsiMethod method, PsiClass containingClass) {
    if (containingClass == null) return false;
    if (method.isConstructor()) {
      if (isSerializable(containingClass, "java.io.Externalizable") && 
          method.getParameterList().getParametersCount() == 0 &&
          method.hasModifierProperty(PsiModifier.PUBLIC)) {
        return true;
      }
      return false;
    }
    if (method.hasModifierProperty(PsiModifier.STATIC)) return false;
    @NonNls String name = method.getName();
    PsiParameter[] parameters = method.getParameterList().getParameters();
    PsiType returnType = method.getReturnType();
    if ("readObjectNoData".equals(name)) {
      return parameters.length == 0 && TypeConversionUtil.isVoidType(returnType) && isSerializable(containingClass);
    }
    if ("readObject".equals(name)) {
      return parameters.length == 1
             && parameters[0].getType().equalsToText("java.io.ObjectInputStream")
             && TypeConversionUtil.isVoidType(returnType) && method.hasModifierProperty(PsiModifier.PRIVATE)
             && isSerializable(containingClass);
    }
    if ("readResolve".equals(name)) {
      return parameters.length == 0
             && returnType != null
             && returnType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)
             && (containingClass.hasModifierProperty(PsiModifier.ABSTRACT) || isSerializable(containingClass));
    }
    if ("writeReplace".equals(name)) {
      return parameters.length == 0
             && returnType != null
             && returnType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)
             && (containingClass.hasModifierProperty(PsiModifier.ABSTRACT) || isSerializable(containingClass));
    }
    if ("writeObject".equals(name)) {
      return parameters.length == 1
             && TypeConversionUtil.isVoidType(returnType)
             && parameters[0].getType().equalsToText("java.io.ObjectOutputStream")
             && method.hasModifierProperty(PsiModifier.PRIVATE)
             && isSerializable(containingClass);
    }
    return false;
  }

  @NotNull
  public static String formatType(@Nullable PsiType type) {
    return type == null ? PsiKeyword.NULL : type.getInternalCanonicalText();
  }

  @Nullable
  private static PsiType getArrayInitializerType(@NotNull PsiArrayInitializerExpression element) {
    PsiType typeCheckResult = sameType(element.getInitializers());
    return typeCheckResult != null ? typeCheckResult.createArrayType() : null;
  }

  @Nullable
  public static PsiType sameType(@NotNull PsiExpression[] expressions) {
    PsiType type = null;
    for (PsiExpression expression : expressions) {
      final PsiType currentType;
      if (expression instanceof PsiArrayInitializerExpression) {
        currentType = getArrayInitializerType((PsiArrayInitializerExpression)expression);
      }
      else {
        currentType = expression.getType();
      }
      if (type == null) {
        type = currentType;
      }
      else if (!type.equals(currentType)) {
        return null;
      }
    }
    return type;
  }

  @NotNull
  public static String formatMethod(@NotNull PsiMethod method) {
    return PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS,
                                      PsiFormatUtilBase.SHOW_TYPE);
  }

  public static boolean isSuperOrThisCall(PsiStatement statement, boolean testForSuper, boolean testForThis) {
    if (!(statement instanceof PsiExpressionStatement)) return false;
    PsiExpression expression = ((PsiExpressionStatement)statement).getExpression();
    if (!(expression instanceof PsiMethodCallExpression)) return false;
    final PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)expression).getMethodExpression();
    if (testForSuper) {
      if ("super".equals(methodExpression.getText())) return true;
    }
    if (testForThis) {
      if ("this".equals(methodExpression.getText())) return true;
    }

    return false;
  }

  /**
   * return all constructors which are referred from this constructor by
   *  this (...) at the beginning of the constructor body
   * @return referring constructor
   */
  @Nullable public static List getChainedConstructors(PsiMethod constructor) {
    final ConstructorVisitorInfo info = new ConstructorVisitorInfo();
    visitConstructorChain(constructor, info);
    if (info.visitedConstructors != null) info.visitedConstructors.remove(constructor);
    return info.visitedConstructors;
  }

  static void visitConstructorChain(PsiMethod constructor, @NotNull ConstructorVisitorInfo info) {
    while (true) {
      if (constructor == null) return;
      final PsiCodeBlock body = constructor.getBody();
      if (body == null) return;
      final PsiStatement[] statements = body.getStatements();
      if (statements.length == 0) return;
      final PsiStatement statement = statements[0];
      final PsiElement element = new PsiMatcherImpl(statement)
          .dot(PsiMatchers.hasClass(PsiExpressionStatement.class))
          .firstChild(PsiMatchers.hasClass(PsiMethodCallExpression.class))
          .firstChild(PsiMatchers.hasClass(PsiReferenceExpression.class))
          .firstChild(PsiMatchers.hasClass(PsiKeyword.class))
          .dot(PsiMatchers.hasText(PsiKeyword.THIS))
          .parent(null)
          .parent(null)
          .getElement();
      if (element == null) return;
      PsiMethodCallExpression methodCall = (PsiMethodCallExpression)element;
      PsiMethod method = methodCall.resolveMethod();
      if (method == null) return;
      if (info.visitedConstructors != null && info.visitedConstructors.contains(method)) {
        info.recursivelyCalledConstructor = method;
        return;
      }
      if (info.visitedConstructors == null) info.visitedConstructors = new ArrayList(5);
      info.visitedConstructors.add(method);
      constructor = method;
    }
  }

  static class ConstructorVisitorInfo {
    List visitedConstructors;
    PsiMethod recursivelyCalledConstructor;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy