Package com.intellij.psi.util

Source Code of com.intellij.psi.util.PropertyUtil

/*
* Copyright 2000-2007 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.psi.util;

import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;

import java.beans.Introspector;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
* @author Mike
*/
public class PropertyUtil {
  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.util.PropertyUtil");

  private PropertyUtil() {
  }

  @SuppressWarnings({"HardCodedStringLiteral"})
  public static boolean isSimplePropertyGetter(PsiMethod method) {
    if (method == null) return false;

    if (method.isConstructor()) return false;

    String methodName = method.getName();
    PsiType returnType = method.getReturnType();
    if (methodName.startsWith("get") && methodName.length() > "get".length()) {
      if (Character.isLowerCase(methodName.charAt("get".length()))
          && (methodName.length() == "get".length() + 1 || Character.isLowerCase(methodName.charAt("get".length() + 1)))) {
        return false;
      }
      if (returnType != null && returnType == PsiType.VOID) return false;
    }
    else if (methodName.startsWith("is")) {
      if (returnType != null && returnType != PsiType.BOOLEAN) return false;
    }
    else {
      return false;
    }

    return method.getParameterList().getParametersCount() == 0;
  }

  @SuppressWarnings("HardCodedStringLiteral")
  public static boolean isSimplePropertySetter(PsiMethod method) {
    if (method == null) return false;

    if (method.isConstructor()) return false;

    String methodName = method.getName();

    if (!(methodName.startsWith("set") && methodName.length() > "set".length())) return false;
    if (Character.isLowerCase(methodName.charAt("set".length()))) return false;

    if (method.getParameterList().getParametersCount() != 1) {
      return false;
    }

    return method.getReturnType() == null || method.getReturnType() == PsiType.VOID;
  }

  @Nullable public static String getPropertyName(PsiMethod method) {
    if (isSimplePropertyGetter(method)) {
      return getPropertyNameByGetter(method);
    }
    else if (isSimplePropertySetter(method)) {
      return getPropertyNameBySetter(method);
    }
    else {
      return null;
    }
  }

  public static String getPropertyNameByGetter(PsiMethod getterMethod) {
    @NonNls String methodName = getterMethod.getName();
    return methodName.startsWith("get") ?
           StringUtil.decapitalize(methodName.substring(3)) :
           StringUtil.decapitalize(methodName.substring(2));
  }

  public static String getPropertyNameBySetter(PsiMethod setterMethod) {
    String methodName = setterMethod.getName();
    return Introspector.decapitalize(methodName.substring(3));
  }

  @Nullable public static PsiMethod findPropertyGetter(PsiClass aClass,
                                                       String propertyName,
                                                       boolean isStatic,
                                                       boolean checkSuperClasses) {
    if (aClass == null) return null;
    PsiMethod[] methods;
    if (checkSuperClasses) {
      methods = aClass.getAllMethods();
    }
    else {
      methods = aClass.getMethods();
    }

    for (PsiMethod method : methods) {
      if (method.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue;

      if (isSimplePropertyGetter(method)) {
        if (getPropertyNameByGetter(method).equals(propertyName)) {
          return method;
        }
      }
    }

    return null;
  }

  @Nullable public static PsiMethod findPropertyGetterWithType(String propertyName, boolean isStatic, PsiType type, Iterator<PsiMethod> methods) {
    while (methods.hasNext()) {
      PsiMethod method = methods.next();
      if (method.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue;
      if (isSimplePropertyGetter(method)) {
        if (getPropertyNameByGetter(method).equals(propertyName)) {
          if (type.equals(method.getReturnType())) return method;
        }
      }
    }
    return null;
  }

  public static boolean isSimplePropertyAccessor(PsiMethod method) {
    return isSimplePropertyGetter(method) || isSimplePropertySetter(method);
  }

  @Nullable public static PsiMethod findPropertySetter(PsiClass aClass,
                                             String propertyName,
                                             boolean isStatic,
                                             boolean checkSuperClasses) {
    if (aClass == null) return null;
    PsiMethod[] methods;
    if (checkSuperClasses) {
      methods = aClass.getAllMethods();
    }
    else {
      methods = aClass.getMethods();
    }

    for (PsiMethod method : methods) {
      if (method.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue;

      if (isSimplePropertySetter(method)) {
        if (getPropertyNameBySetter(method).equals(propertyName)) {
          return method;
        }
      }
    }

    return null;
  }

  @Nullable public static PsiMethod findPropertySetterWithType(String propertyName, boolean isStatic, PsiType type, Iterator<PsiMethod> methods) {
    while (methods.hasNext()) {
      PsiMethod method = methods.next();
      if (method.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue;

      if (isSimplePropertySetter(method)) {
        if (getPropertyNameBySetter(method).equals(propertyName)) {
          PsiType methodType = method.getParameterList().getParameters()[0].getType();
          if (type.equals(methodType)) return method;
        }
      }
    }
    return null;
  }

  @Nullable public static PsiField findPropertyField(Project project, PsiClass aClass, String propertyName, boolean isStatic) {
    PsiField[] fields = aClass.getAllFields();

    for (PsiField field : fields) {
      if (field.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue;
      if (propertyName.equals(suggestPropertyName(project, field))) return field;
    }

    return null;
  }

  @Nullable public static PsiField findPropertyFieldWithType(Project project, String propertyName,
                                                   boolean isStatic, PsiType type, Iterator<PsiField> fields) {
    while (fields.hasNext()) {
      PsiField field = fields.next();
      if (field.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue;
      if (propertyName.equals(suggestPropertyName(project, field))) {
        if (type.equals(field.getType())) return field;
      }
    }

    return null;
  }

  @Nullable public static String getPropertyName(@NonNls String methodName) {
    if (methodName.startsWith("get")) {
      return Introspector.decapitalize(methodName.substring(3));
    }
    else if (methodName.startsWith("is")) {
      return Introspector.decapitalize(methodName.substring(2));
    }
    else if (methodName.startsWith("set")) {
      return Introspector.decapitalize(methodName.substring(3));
    }
    else {
      return null;
    }
  }

  public static String suggestGetterName(String propertyName, PsiType propertyType) {
    return suggestGetterName(propertyName, propertyType, null);
  }

  @SuppressWarnings({"HardCodedStringLiteral"})
  public static String suggestGetterName(String propertyName, PsiType propertyType, String existingGetterName) {
    StringBuffer name = new StringBuffer(StringUtil.capitalize(propertyName));
    if (propertyType == PsiType.BOOLEAN) {
      if (existingGetterName == null || !existingGetterName.startsWith("get")) {
        name.insert(0, "is");
      }
      else {
        name.insert(0, "get");
      }
    }
    else {
      name.insert(0, "get");
    }

    return name.toString();
  }

  public static String suggestSetterName(String propertyName) {
    @NonNls StringBuffer name = new StringBuffer(StringUtil.capitalize(propertyName));
    name.insert(0, "set");
    return name.toString();
  }

  public static String[] getReadableProperties(PsiClass aClass, boolean includeSuperClass) {
    List<String> result = new ArrayList<String>();

    PsiMethod[] methods;
    if (includeSuperClass) {
      methods = aClass.getAllMethods();
    }
    else {
      methods = aClass.getMethods();
    }

    for (PsiMethod method : methods) {
      if ("java.lang.Object".equals(method.getContainingClass().getQualifiedName())) continue;

      if (isSimplePropertyGetter(method)) {
        result.add(getPropertyName(method));
      }
    }

    return result.toArray(new String[result.size()]);
  }

  public static String[] getWritableProperties(PsiClass aClass, boolean includeSuperClass) {
    List<String> result = new ArrayList<String>();

    PsiMethod[] methods;

    if (includeSuperClass) {
      methods = aClass.getAllMethods();
    }
    else {
      methods = aClass.getMethods();
    }

    for (PsiMethod method : methods) {
      if ("java.lang.Object".equals(method.getContainingClass().getQualifiedName())) continue;

      if (isSimplePropertySetter(method)) {
        result.add(getPropertyName(method));
      }
    }

    return result.toArray(new String[result.size()]);
  }

  public static PsiMethod generateGetterPrototype(PsiField field) {
    PsiElementFactory factory = field.getManager().getElementFactory();
    Project project = field.getProject();
    String name = field.getName();
    String getName = suggestGetterName(project, field);
    try {
      PsiMethod getMethod = factory.createMethod(getName, field.getType());
      getMethod.getModifierList().setModifierProperty(PsiModifier.PUBLIC, true);
      if (field.hasModifierProperty(PsiModifier.STATIC)) {
        getMethod.getModifierList().setModifierProperty(PsiModifier.STATIC, true);
      }

      annotateWithNullableStuff(field, factory, getMethod);

      PsiCodeBlock body = factory.createCodeBlockFromText("{\nreturn " + name + ";\n}", null);
      getMethod.getBody().replace(body);
      getMethod = (PsiMethod)CodeStyleManager.getInstance(project).reformat(getMethod);
      return getMethod;
    }
    catch (IncorrectOperationException e) {
      LOG.error(e);
      return null;
    }
  }

  public static PsiMethod generateSetterPrototype(PsiField field) {
    return generateSetterPrototype(field, field.getContainingClass());
  }

  public static PsiMethod generateSetterPrototype(PsiField field, final PsiClass containingClass) {
    Project project = field.getProject();
    CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
    PsiElementFactory factory = field.getManager().getElementFactory();

    String name = field.getName();
    boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
    VariableKind kind = codeStyleManager.getVariableKind(field);
    String propertyName = codeStyleManager.variableNameToPropertyName(name, kind);
    String setName = suggestSetterName(project, field);
    try {
      PsiMethod setMethod = factory.createMethod(setName, PsiType.VOID);
      String parameterName = codeStyleManager.propertyNameToVariableName(propertyName, VariableKind.PARAMETER);
      PsiParameter param = factory.createParameter(parameterName, field.getType());

      annotateWithNullableStuff(field, factory, param);

      setMethod.getParameterList().add(param);
      setMethod.getModifierList().setModifierProperty(PsiModifier.PUBLIC, true);
      setMethod.getModifierList().setModifierProperty(PsiModifier.STATIC, isStatic);

      @NonNls StringBuffer buffer = new StringBuffer();
      buffer.append("{\n");
      if (name.equals(parameterName)) {
        if (!isStatic) {
          buffer.append("this.");
        }
        else {
          String className = containingClass.getName();
          if (className != null) {
            buffer.append(className);
            buffer.append(".");
          }
        }
      }
      buffer.append(name);
      buffer.append("=");
      buffer.append(parameterName);
      buffer.append(";\n}");
      PsiCodeBlock body = factory.createCodeBlockFromText(buffer.toString(), null);
      setMethod.getBody().replace(body);
      setMethod = (PsiMethod)codeStyleManager.reformat(setMethod);
      return setMethod;
    }
    catch (IncorrectOperationException e) {
      LOG.error(e);
      return null;
    }
  }

  private static void annotateWithNullableStuff(final PsiModifierListOwner field, final PsiElementFactory factory, final PsiModifierListOwner listOwner)
    throws IncorrectOperationException {
    if (AnnotationUtil.isAnnotated(field, AnnotationUtil.NOT_NULL, false)) {
      annotate(factory, listOwner, AnnotationUtil.NOT_NULL);
    }
    else if (AnnotationUtil.isAnnotated(field, AnnotationUtil.NULLABLE, false)) {
      annotate(factory, listOwner, AnnotationUtil.NULLABLE);
    }
  }

  private static void annotate(final PsiElementFactory factory, final PsiModifierListOwner listOwner, final String annotationQName)
    throws IncorrectOperationException {
    final PsiModifierList modifierList = listOwner.getModifierList();
    LOG.assertTrue(modifierList != null);
    modifierList.addAfter(factory.createAnnotationFromText("@" + annotationQName, listOwner), null);
  }

  public static String suggestPropertyName(Project project, PsiField field) {
    CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
    VariableKind kind = codeStyleManager.getVariableKind(field);
    return codeStyleManager.variableNameToPropertyName(field.getName(), kind);
  }

  public static String suggestGetterName(Project project, PsiField field) {
    String propertyName = suggestPropertyName(project, field);
    return suggestGetterName(propertyName, field.getType());
  }

  public static String suggestSetterName(Project project, PsiField field) {
    String propertyName = suggestPropertyName(project, field);
    return suggestSetterName(propertyName);
  }

  /**
   *  "xxx", "void setMyProperty(String pp)" -> "setXxx"
   */
  @Nullable public static String suggestPropertyAccessor(String name, PsiMethod accessorTemplate) {
    if (isSimplePropertyGetter(accessorTemplate)) {
      PsiType type = accessorTemplate.getReturnType();
      return suggestGetterName(name, type, accessorTemplate.getName());
    }
    if (isSimplePropertySetter(accessorTemplate)) {
      return suggestSetterName(name);
    }
    return null;
  }

  @Nullable
  public static String getPropertyName(final PsiMember member) {
    if (member instanceof PsiMethod) {
      return getPropertyName((PsiMethod)member);
    }
    else if (member instanceof PsiField) {
      return member.getName();
    }
    else return null;
  }

  @Nullable
  public static PsiType getPropertyType(final PsiMember member) {
    if (member instanceof PsiField) {
      return ((PsiField)member).getType();
    }
    else if (member instanceof PsiMethod) {
      final PsiMethod psiMethod = (PsiMethod)member;
      if (isSimplePropertyGetter(psiMethod)) {
        return psiMethod.getReturnType();
      }
      else if (isSimplePropertySetter(psiMethod)) {
        return psiMethod.getParameterList().getParameters()[0].getType();
      }
    }
    return null;
  }

  @Nullable
  public static PsiTypeElement getPropertyTypeElement(final PsiMember member) {
    if (member instanceof PsiField) {
      return ((PsiField)member).getTypeElement();
    }
    else if (member instanceof PsiMethod) {
      final PsiMethod psiMethod = (PsiMethod)member;
      if (isSimplePropertyGetter(psiMethod)) {
        return psiMethod.getReturnTypeElement();
      }
      else if (isSimplePropertySetter(psiMethod)) {
        return psiMethod.getParameterList().getParameters()[0].getTypeElement();
      }
    }
    return null;
  }

  @Nullable
  public static PsiIdentifier getPropertyNameIdentifier(final PsiMember member) {
    if (member instanceof PsiField) {
      return ((PsiField)member).getNameIdentifier();
    }
    else if (member instanceof PsiMethod) {
      return ((PsiMethod)member).getNameIdentifier();
    }
    return null;
  }
}
TOP

Related Classes of com.intellij.psi.util.PropertyUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.