2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.plugins.groovy.lang.psi.util;
18 import com.intellij.openapi.project.Project;
19 import com.intellij.openapi.util.text.StringUtil;
20 import com.intellij.psi.*;
21 import com.intellij.psi.util.PropertyUtil;
22 import com.intellij.util.ArrayUtil;
23 import org.jetbrains.annotations.NonNls;
24 import org.jetbrains.annotations.NotNull;
25 import org.jetbrains.annotations.Nullable;
26 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
27 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
28 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
30 import java.beans.Introspector;
35 public class GroovyPropertyUtils {
36 private static final String IS_PREFIX = "is";
37 private static final String GET_PREFIX = "get";
38 private static final String SET_PREFIX = "set";
40 private GroovyPropertyUtils() {
44 public static PsiMethod findSetterForField(PsiField field) {
45 final PsiClass containingClass = field.getContainingClass();
46 final Project project = field.getProject();
47 final String propertyName = PropertyUtil.suggestPropertyName(project, field);
48 final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
49 return findPropertySetter(containingClass, propertyName, isStatic, true);
53 public static PsiMethod findGetterForField(PsiField field) {
54 final PsiClass containingClass = field.getContainingClass();
55 final Project project = field.getProject();
56 final String propertyName = PropertyUtil.suggestPropertyName(project, field);
57 final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
58 return PropertyUtil.findPropertyGetter(containingClass, propertyName, isStatic, true);
62 public static PsiMethod findPropertySetter(PsiClass aClass, String propertyName, boolean isStatic, boolean checkSuperClasses) {
63 if (aClass == null) return null;
65 if (checkSuperClasses) {
66 methods = aClass.getAllMethods();
69 methods = aClass.getMethods();
72 for (PsiMethod method : methods) {
73 if (method.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue;
75 if (isSimplePropertySetter(method)) {
76 if (propertyName.equals(getPropertyNameBySetter(method))) {
86 public static PsiMethod findPropertyGetter(PsiClass aClass, String propertyName, boolean isStatic, boolean checkSuperClasses) {
87 if (aClass == null) return null;
89 if (checkSuperClasses) {
90 methods = aClass.getAllMethods();
93 methods = aClass.getMethods();
96 for (PsiMethod method : methods) {
97 if (method.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue;
99 if (isSimplePropertyGetter(method)) {
100 if (propertyName.equals(getPropertyNameByGetter(method))) {
109 public static boolean isSimplePropertyAccessor(PsiMethod method) {
110 return isSimplePropertyGetter(method) || isSimplePropertySetter(method);
111 }//do not check return type
113 public static boolean isSimplePropertyGetter(PsiMethod method) {
114 return isSimplePropertyGetter(method, null);
115 }//do not check return type
117 public static boolean isSimplePropertyGetter(PsiMethod method, String propertyName) {
118 if (method == null || method.isConstructor()) return false;
119 if (method.getParameterList().getParametersCount() != 0) return false;
120 if (!isGetterName(method.getName())) return false;
121 if (method.getName().startsWith(IS_PREFIX) && !PsiType.BOOLEAN.equals(method.getReturnType())) {
124 return (propertyName == null || propertyName.equals(getPropertyNameByGetter(method))) && method.getReturnType() != PsiType.VOID;
127 public static boolean isSimplePropertySetter(PsiMethod method) {
128 return isSimplePropertySetter(method, null);
131 public static boolean isSimplePropertySetter(PsiMethod method, String propertyName) {
132 if (method == null || method.isConstructor()) return false;
133 if (method.getParameterList().getParametersCount() != 1) return false;
134 if (!isSetterName(method.getName())) return false;
135 return propertyName == null || propertyName.equals(getPropertyNameBySetter(method));
139 public static String getPropertyNameByGetter(PsiMethod getterMethod) {
140 if (getterMethod instanceof GrAccessorMethod) {
141 return ((GrAccessorMethod)getterMethod).getProperty().getName();
144 @NonNls String methodName = getterMethod.getName();
145 final boolean isPropertyBoolean = PsiType.BOOLEAN.equals(getterMethod.getReturnType());
146 return getPropertyNameByGetterName(methodName, isPropertyBoolean);
150 public static String getPropertyNameByGetterName(String methodName, boolean canBeBoolean) {
151 if (methodName.startsWith(GET_PREFIX) && methodName.length() > 3) {
152 return decapitalize(methodName.substring(3));
154 if (canBeBoolean && methodName.startsWith(IS_PREFIX) && methodName.length() > 2) {
155 return decapitalize(methodName.substring(2));
161 public static String getPropertyNameBySetter(PsiMethod setterMethod) {
162 if (setterMethod instanceof GrAccessorMethod) {
163 return ((GrAccessorMethod)setterMethod).getProperty().getName();
166 @NonNls String methodName = setterMethod.getName();
167 return getPropertyNameBySetterName(methodName);
171 public static String getPropertyNameBySetterName(String methodName) {
172 if (methodName.startsWith(SET_PREFIX) && methodName.length() > 3) {
173 return StringUtil.decapitalize(methodName.substring(3));
181 public static String getPropertyNameByAccessorName(String accessorName) {
182 if (isGetterName(accessorName)) {
183 return getPropertyNameByGetterName(accessorName, true);
185 else if (isSetterName(accessorName)) {
186 return getPropertyNameBySetterName(accessorName);
192 public static String getPropertyName(PsiMethod accessor) {
193 if (isSimplePropertyGetter(accessor)) return getPropertyNameByGetter(accessor);
194 if (isSimplePropertySetter(accessor)) return getPropertyNameBySetter(accessor);
198 public static boolean isGetterName(@NotNull String name) {
199 if (name.startsWith(GET_PREFIX) && name.length() > 3 && isUpperCase(name.charAt(3))) return true;
200 if (name.startsWith(IS_PREFIX) && name.length() > 2 && isUpperCase(name.charAt(2))) return true;
205 * Returns getter names in priority order
207 * @param name property name
208 * @return getter names
210 public static String[] suggestGettersName(@NotNull String name) {
211 return new String[]{IS_PREFIX + capitalize(name), GET_PREFIX + capitalize(name)};
214 public static String[] suggestSettersName(@NotNull String name) {
215 return new String[]{SET_PREFIX + capitalize(name)};
218 public static boolean isSetterName(String name) {
219 return name != null && name.startsWith(SET_PREFIX) && name.length() > 3 && isUpperCase(name.charAt(3));
222 public static boolean isProperty(@Nullable PsiClass aClass, @Nullable String propertyName, boolean isStatic) {
223 if (aClass == null || propertyName == null) return false;
224 final PsiField field = aClass.findFieldByName(propertyName, true);
225 if (field instanceof GrField && ((GrField)field).isProperty() && field.hasModifierProperty(PsiModifier.STATIC) == isStatic) return true;
227 final PsiMethod getter = findPropertyGetter(aClass, propertyName, isStatic, true);
228 if (getter != null && getter.hasModifierProperty(PsiModifier.PUBLIC)) return true;
230 final PsiMethod setter = findPropertySetter(aClass, propertyName, isStatic, true);
231 return setter != null && setter.hasModifierProperty(PsiModifier.PUBLIC);
234 public static boolean isProperty(GrField field) {
235 final PsiClass clazz = field.getContainingClass();
236 return isProperty(clazz, field.getName(), field.hasModifierProperty(PsiModifier.STATIC));
239 private static boolean isUpperCase(char c) {
240 return Character.toUpperCase(c) == c;
243 /*public static boolean canBePropertyName(String name) {
244 return !(name.length() > 1 && Character.isUpperCase(name.charAt(1)) && Character.isLowerCase(name.charAt(0)));
247 public static String capitalize(String s) {
248 if (s.length() == 0) return s;
249 if (s.length() == 1) return s.toUpperCase();
250 if (Character.isUpperCase(s.charAt(1))) return s;
251 final char[] chars = s.toCharArray();
252 chars[0] = Character.toUpperCase(chars[0]);
253 return new String(chars);
256 public static String decapitalize(String s) {
257 return Introspector.decapitalize(s);
261 public static PsiField findFieldForAccessor(PsiMethod accessor, boolean checkSuperClasses) {
262 final PsiClass psiClass = accessor.getContainingClass();
263 if (psiClass == null) return null;
264 PsiField field = null;
265 if (!checkSuperClasses) {
266 field = psiClass.findFieldByName(getPropertyNameByAccessorName(accessor.getName()), true);
269 final String name = getPropertyNameByAccessorName(accessor.getName());
271 final PsiField[] allFields = psiClass.getAllFields();
272 for (PsiField psiField : allFields) {
273 if (name.equals(psiField.getName())) {
279 if (field == null) return null;
280 if (field.hasModifierProperty(GrModifier.STATIC) == accessor.hasModifierProperty(GrModifier.STATIC)) {
287 public static String getGetterPrefix(PsiMethod getter) {
288 final String name = getter.getName();
289 if (name.startsWith(GET_PREFIX)) return GET_PREFIX;
290 if (name.startsWith(IS_PREFIX)) return IS_PREFIX;
296 public static String getSetterPrefix(PsiMethod setter) {
297 if (setter.getName().startsWith(SET_PREFIX)) return SET_PREFIX;
302 public static String getAccessorPrefix(PsiMethod method) {
303 final String prefix = getGetterPrefix(method);
304 if (prefix != null) return prefix;
306 return getSetterPrefix(method);
309 public static boolean isAccessorFor(PsiMethod accessor, PsiField field) {
310 final String accessorName = accessor.getName();
311 final String fieldName = field.getName();
312 if (!ArrayUtil.contains(accessorName, suggestGettersName(fieldName)) &&
313 !ArrayUtil.contains(accessorName, suggestSettersName(fieldName))) {
316 final PsiClass accessorClass = accessor.getContainingClass();
317 final PsiClass fieldClass = field.getContainingClass();
318 if (!field.getManager().areElementsEquivalent(accessorClass, fieldClass)) return false;
319 return accessor.hasModifierProperty(GrModifier.STATIC) == field.hasModifierProperty(GrModifier.STATIC);