mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
Move MethodReferencesSearch (and necessary closure) to java-indexing-api.
Remove references to StfFileTypes from SimpleAccessorReferencesSearch and extract them into one more CustomPropertyScopeProvider
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="core-api" exported="" />
|
||||
<orderEntry type="module" module-name="projectModel-api" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class AnnotationUtil {
|
||||
/**
|
||||
* The full qualified name of the standard Nullable annotation.
|
||||
*/
|
||||
public static final String NULLABLE = "org.jetbrains.annotations.Nullable";
|
||||
|
||||
/**
|
||||
* The full qualified name of the standard NotNull annotation.
|
||||
*/
|
||||
public static final String NOT_NULL = "org.jetbrains.annotations.NotNull";
|
||||
|
||||
@NonNls public static final String NOT_NULL_SIMPLE_NAME = "NotNull";
|
||||
|
||||
@NonNls public static final String NULLABLE_SIMPLE_NAME = "Nullable";
|
||||
|
||||
/**
|
||||
* The full qualified name of the standard NonNls annotation.
|
||||
*
|
||||
* @since 5.0.1
|
||||
*/
|
||||
public static final String NON_NLS = "org.jetbrains.annotations.NonNls";
|
||||
public static final String NLS = "org.jetbrains.annotations.Nls";
|
||||
public static final String PROPERTY_KEY = "org.jetbrains.annotations.PropertyKey";
|
||||
@NonNls public static final String PROPERTY_KEY_RESOURCE_BUNDLE_PARAMETER = "resourceBundle";
|
||||
|
||||
@NonNls public static final String NON_NLS_SIMPLE_NAME = "NonNls";
|
||||
@NonNls public static final String PROPERTY_KEY_SIMPLE_NAME = "PropertyKey";
|
||||
|
||||
public static final String TEST_ONLY = "org.jetbrains.annotations.TestOnly";
|
||||
@NonNls public static final String TEST_ONLY_SIMPLE_NAME = "TestOnly";
|
||||
|
||||
public static final String LANGUAGE = "org.intellij.lang.annotations.Language";
|
||||
|
||||
public static final Set<String> ALL_ANNOTATIONS;
|
||||
|
||||
@NonNls private static final String[] SIMPLE_NAMES =
|
||||
{NOT_NULL_SIMPLE_NAME, NULLABLE_SIMPLE_NAME, NON_NLS_SIMPLE_NAME, PROPERTY_KEY_SIMPLE_NAME, TEST_ONLY_SIMPLE_NAME,
|
||||
"Language", "Identifier", "Pattern", "PrintFormat", "RegExp", "Subst"};
|
||||
|
||||
static {
|
||||
ALL_ANNOTATIONS = new HashSet<String>(2);
|
||||
ALL_ANNOTATIONS.add(NULLABLE);
|
||||
ALL_ANNOTATIONS.add(NOT_NULL);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiAnnotation findAnnotation(PsiModifierListOwner listOwner, @NotNull String... annotationNames) {
|
||||
return findAnnotation(listOwner, false, annotationNames);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiAnnotation findAnnotation(PsiModifierListOwner listOwner, final boolean skipExternal, @NotNull String... annotationNames) {
|
||||
if (annotationNames.length == 0) return null;
|
||||
Set<String> set = annotationNames.length == 1 ? Collections.singleton(annotationNames[0]) : new HashSet<String>(Arrays.asList(annotationNames));
|
||||
return findAnnotation(listOwner, set, skipExternal);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, @NotNull Set<String> annotationNames) {
|
||||
return findAnnotation(listOwner, (Collection<String>)annotationNames);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, Collection<String> annotationNames) {
|
||||
return findAnnotation(listOwner, annotationNames, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, @NotNull Collection<String> annotationNames,
|
||||
final boolean skipExternal) {
|
||||
if (listOwner == null) return null;
|
||||
final PsiModifierList list = listOwner.getModifierList();
|
||||
if (list == null) return null;
|
||||
final PsiAnnotation[] allAnnotations = list.getAnnotations();
|
||||
for (PsiAnnotation annotation : allAnnotations) {
|
||||
String qualifiedName = annotation.getQualifiedName();
|
||||
if (annotationNames.contains(qualifiedName)) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
if (!skipExternal) {
|
||||
final ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(listOwner.getProject());
|
||||
for (String annotationName : annotationNames) {
|
||||
final PsiAnnotation annotation = annotationsManager.findExternalAnnotation(listOwner, annotationName);
|
||||
if (annotation != null) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiAnnotation[] findAnnotations(final PsiModifierListOwner modifierListOwner, @NotNull Collection<String> annotationNames) {
|
||||
if (modifierListOwner == null) return PsiAnnotation.EMPTY_ARRAY;
|
||||
final PsiModifierList modifierList = modifierListOwner.getModifierList();
|
||||
if (modifierList == null) return PsiAnnotation.EMPTY_ARRAY;
|
||||
final PsiAnnotation[] annotations = modifierList.getAnnotations();
|
||||
ArrayList<PsiAnnotation> result = null;
|
||||
for (final PsiAnnotation psiAnnotation : annotations) {
|
||||
if (annotationNames.contains(psiAnnotation.getQualifiedName())) {
|
||||
if (result == null) result = new ArrayList<PsiAnnotation>();
|
||||
result.add(psiAnnotation);
|
||||
}
|
||||
}
|
||||
return result == null ? PsiAnnotation.EMPTY_ARRAY : result.toArray(new PsiAnnotation[result.size()]);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiAnnotation findAnnotationInHierarchy(PsiModifierListOwner listOwner, @NotNull Set<String> annotationNames) {
|
||||
PsiAnnotation directAnnotation = findAnnotation(listOwner, annotationNames);
|
||||
if (directAnnotation != null) return directAnnotation;
|
||||
if (listOwner instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)listOwner;
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) return null;
|
||||
HierarchicalMethodSignature methodSignature = method.getHierarchicalMethodSignature();
|
||||
return findAnnotationInHierarchy(methodSignature, annotationNames, method, null,
|
||||
JavaPsiFacade.getInstance(method.getProject()).getResolveHelper());
|
||||
}
|
||||
if (listOwner instanceof PsiClass) {
|
||||
return findAnnotationInHierarchy((PsiClass)listOwner, annotationNames, null);
|
||||
}
|
||||
if (listOwner instanceof PsiParameter) {
|
||||
PsiParameter parameter = (PsiParameter)listOwner;
|
||||
return doFindAnnotationInHierarchy(parameter, annotationNames, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiAnnotation doFindAnnotationInHierarchy(PsiParameter parameter,
|
||||
Set<String> annotationNames,
|
||||
@Nullable Set<PsiModifierListOwner> visited) {
|
||||
PsiAnnotation annotation = findAnnotation(parameter, annotationNames);
|
||||
if (annotation != null) return annotation;
|
||||
PsiElement scope = parameter.getDeclarationScope();
|
||||
if (!(scope instanceof PsiMethod)) {
|
||||
return null;
|
||||
}
|
||||
PsiMethod method = (PsiMethod)scope;
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
PsiElement parent = parameter.getParent();
|
||||
if (aClass == null || !(parent instanceof PsiParameterList)) {
|
||||
return null;
|
||||
}
|
||||
int index = ((PsiParameterList)parent).getParameterIndex(parameter);
|
||||
HierarchicalMethodSignature methodSignature = method.getHierarchicalMethodSignature();
|
||||
|
||||
final List<HierarchicalMethodSignature> superSignatures = methodSignature.getSuperSignatures();
|
||||
PsiResolveHelper resolveHelper = PsiResolveHelper.SERVICE.getInstance(aClass.getProject());
|
||||
for (final HierarchicalMethodSignature superSignature : superSignatures) {
|
||||
final PsiMethod superMethod = superSignature.getMethod();
|
||||
if (visited == null) visited = new THashSet<PsiModifierListOwner>();
|
||||
if (!visited.add(superMethod)) continue;
|
||||
if (!resolveHelper.isAccessible(superMethod, parameter, null)) continue;
|
||||
PsiParameter[] superParameters = superMethod.getParameterList().getParameters();
|
||||
if (index < superParameters.length) {
|
||||
PsiAnnotation insuper = doFindAnnotationInHierarchy(superParameters[index], annotationNames, visited);
|
||||
if (insuper != null) return insuper;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiAnnotation findAnnotationInHierarchy(@NotNull final PsiClass psiClass, final Set<String> annotationNames, @Nullable Set<PsiClass> processed) {
|
||||
final PsiClass[] superClasses = psiClass.getSupers();
|
||||
for (final PsiClass superClass : superClasses) {
|
||||
if (processed == null) processed = new THashSet<PsiClass>();
|
||||
if (!processed.add(superClass)) return null;
|
||||
final PsiAnnotation annotation = findAnnotation(superClass, annotationNames);
|
||||
if (annotation != null) return annotation;
|
||||
final PsiAnnotation annotationInHierarchy = findAnnotationInHierarchy(superClass, annotationNames, processed);
|
||||
if (annotationInHierarchy != null) return annotationInHierarchy;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiAnnotation findAnnotationInHierarchy(@NotNull HierarchicalMethodSignature signature,
|
||||
@NotNull Set<String> annotationNames,
|
||||
@NotNull PsiElement place,
|
||||
@Nullable Set<PsiMethod> processed,
|
||||
@NotNull PsiResolveHelper resolveHelper) {
|
||||
final List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
|
||||
for (final HierarchicalMethodSignature superSignature : superSignatures) {
|
||||
final PsiMethod superMethod = superSignature.getMethod();
|
||||
if (processed == null) processed = new THashSet<PsiMethod>();
|
||||
if (!processed.add(superMethod)) continue;
|
||||
if (!resolveHelper.isAccessible(superMethod, place, null)) continue;
|
||||
PsiAnnotation direct = findAnnotation(superMethod, annotationNames);
|
||||
if (direct != null) return direct;
|
||||
PsiAnnotation superResult = findAnnotationInHierarchy(superSignature, annotationNames, place, processed, resolveHelper);
|
||||
if (superResult != null) return superResult;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, Collection<String> annotations) {
|
||||
return isAnnotated(listOwner, annotations, false);
|
||||
}
|
||||
|
||||
public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner,
|
||||
Collection<String> annotations,
|
||||
final boolean checkHierarchy) {
|
||||
for (String annotation : annotations) {
|
||||
if (isAnnotated(listOwner, annotation, checkHierarchy)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, @NonNls String annotationFQN, boolean checkHierarchy) {
|
||||
return isAnnotated(listOwner, annotationFQN, checkHierarchy, false, null);
|
||||
}
|
||||
|
||||
public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, @NonNls String annotationFQN, boolean checkHierarchy,
|
||||
boolean skipExternal) {
|
||||
return isAnnotated(listOwner, annotationFQN, checkHierarchy, skipExternal, null);
|
||||
}
|
||||
|
||||
private static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner,
|
||||
@NonNls String annotationFQN,
|
||||
boolean checkHierarchy, final boolean skipExternal, @Nullable Set<PsiMember> processed) {
|
||||
if (!listOwner.isValid()) return false;
|
||||
final PsiModifierList modifierList = listOwner.getModifierList();
|
||||
if (modifierList == null) return false;
|
||||
PsiAnnotation annotation = modifierList.findAnnotation(annotationFQN);
|
||||
if (annotation != null) return true;
|
||||
if (!skipExternal && ExternalAnnotationsManager.getInstance(listOwner.getProject()).findExternalAnnotation(listOwner, annotationFQN) != null) {
|
||||
return true;
|
||||
}
|
||||
if (checkHierarchy) {
|
||||
if (listOwner instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)listOwner;
|
||||
if (processed == null) processed = new THashSet<PsiMember>();
|
||||
if (!processed.add(method)) return false;
|
||||
final PsiMethod[] superMethods = method.findSuperMethods();
|
||||
for (PsiMethod superMethod : superMethods) {
|
||||
if (isAnnotated(superMethod, annotationFQN, checkHierarchy, skipExternal, processed)) return true;
|
||||
}
|
||||
} else if (listOwner instanceof PsiClass) {
|
||||
final PsiClass clazz = (PsiClass)listOwner;
|
||||
if (processed == null) processed = new THashSet<PsiMember>();
|
||||
if (!processed.add(clazz)) return false;
|
||||
final PsiClass[] superClasses = clazz.getSupers();
|
||||
for (PsiClass superClass : superClasses) {
|
||||
if (isAnnotated(superClass, annotationFQN, checkHierarchy, skipExternal, processed)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isAnnotatingApplicable(@NotNull PsiElement elt) {
|
||||
final Project project = elt.getProject();
|
||||
return PsiUtil.isLanguageLevel5OrHigher(elt) &&
|
||||
JavaPsiFacade.getInstance(project).findClass(NullableNotNullManager.getInstance(project).getDefaultNullable(), elt.getResolveScope()) != null;
|
||||
}
|
||||
|
||||
public static boolean isJetbrainsAnnotation(@NonNls final String simpleName) {
|
||||
return ArrayUtil.find(SIMPLE_NAMES, simpleName) != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Works similar to #isAnnotated(PsiModifierListOwner, Collection<String>) but supports FQN patters
|
||||
* like "javax.ws.rs.*". Supports ending "*" only.
|
||||
*
|
||||
* @param owner modifier list
|
||||
* @param annotations annotations qualified names or patterns. Patterns can have '*' at the end
|
||||
* @return <code>true</code> if annotated of at least one annotation from the annotations list
|
||||
*/
|
||||
public static boolean checkAnnotatedUsingPatterns(PsiModifierListOwner owner, Collection<String> annotations) {
|
||||
final PsiModifierList modList;
|
||||
if (owner == null || (modList = owner.getModifierList()) == null) return false;
|
||||
|
||||
List<String> fqns = null;
|
||||
for (String fqn : annotations) {
|
||||
boolean isPattern = fqn.endsWith("*");
|
||||
if (!isPattern && isAnnotated(owner, fqn, false)) {
|
||||
return true;
|
||||
} else if (isPattern) {
|
||||
if (fqns == null) {
|
||||
fqns = new ArrayList<String>();
|
||||
final PsiAnnotation[] annos = modList.getAnnotations();
|
||||
for (PsiAnnotation anno : annos) {
|
||||
final String qName = anno.getQualifiedName();
|
||||
if (qName != null) {
|
||||
fqns.add(qName);
|
||||
}
|
||||
}
|
||||
if (fqns.isEmpty()) return false;
|
||||
}
|
||||
fqn = fqn.substring(0, fqn.length() - 2);
|
||||
for (String annoFQN : fqns) {
|
||||
if (annoFQN.startsWith(fqn)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod getAnnotationMethod(PsiNameValuePair pair) {
|
||||
final PsiAnnotation annotation = PsiTreeUtil.getParentOfType(pair.getParent(), PsiAnnotation.class);
|
||||
assert annotation != null;
|
||||
|
||||
final String fqn = annotation.getQualifiedName();
|
||||
if (fqn == null) return null;
|
||||
|
||||
final PsiClass psiClass = JavaPsiFacade.getInstance(pair.getProject()).findClass(fqn, pair.getResolveScope());
|
||||
if (psiClass != null && psiClass.isAnnotationType()) {
|
||||
final String name = pair.getName();
|
||||
return ArrayUtil.getFirstElement(psiClass.findMethodsByName(name != null ? name : "value", false));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner, boolean inHierarchy, Set<PsiModifierListOwner> visited) {
|
||||
final PsiModifierList list = owner.getModifierList();
|
||||
PsiAnnotation[] annotations = PsiAnnotation.EMPTY_ARRAY;
|
||||
if (list != null) {
|
||||
annotations = list.getAnnotations();
|
||||
}
|
||||
|
||||
final PsiAnnotation[] externalAnnotations = ExternalAnnotationsManager.getInstance(owner.getProject()).findExternalAnnotations(owner);
|
||||
if (externalAnnotations != null) {
|
||||
annotations = ArrayUtil.mergeArrays(annotations, externalAnnotations, PsiAnnotation.ARRAY_FACTORY);
|
||||
}
|
||||
|
||||
if (inHierarchy) {
|
||||
if (owner instanceof PsiClass) {
|
||||
for (PsiClass superClass : ((PsiClass)owner).getSupers()) {
|
||||
if (visited == null) visited = new THashSet<PsiModifierListOwner>();
|
||||
if (visited.add(superClass)) annotations = ArrayUtil.mergeArrays(annotations, getAllAnnotations(superClass, inHierarchy, visited));
|
||||
}
|
||||
}
|
||||
else if (owner instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)owner;
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass != null) {
|
||||
HierarchicalMethodSignature methodSignature = method.getHierarchicalMethodSignature();
|
||||
|
||||
final List<HierarchicalMethodSignature> superSignatures = methodSignature.getSuperSignatures();
|
||||
PsiResolveHelper resolveHelper = PsiResolveHelper.SERVICE.getInstance(aClass.getProject());
|
||||
for (final HierarchicalMethodSignature superSignature : superSignatures) {
|
||||
final PsiMethod superMethod = superSignature.getMethod();
|
||||
if (visited == null) visited = new THashSet<PsiModifierListOwner>();
|
||||
if (!visited.add(superMethod)) continue;
|
||||
if (!resolveHelper.isAccessible(superMethod, owner, null)) continue;
|
||||
annotations = ArrayUtil.mergeArrays(annotations, getAllAnnotations(superMethod, inHierarchy, visited));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (owner instanceof PsiParameter) {
|
||||
PsiParameter parameter = (PsiParameter)owner;
|
||||
PsiElement scope = parameter.getDeclarationScope();
|
||||
if (scope instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)scope;
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
PsiElement parent = parameter.getParent();
|
||||
if (aClass != null && parent instanceof PsiParameterList) {
|
||||
int index = ((PsiParameterList)parent).getParameterIndex(parameter);
|
||||
HierarchicalMethodSignature methodSignature = method.getHierarchicalMethodSignature();
|
||||
|
||||
final List<HierarchicalMethodSignature> superSignatures = methodSignature.getSuperSignatures();
|
||||
PsiResolveHelper resolveHelper = PsiResolveHelper.SERVICE.getInstance(aClass.getProject());
|
||||
for (final HierarchicalMethodSignature superSignature : superSignatures) {
|
||||
final PsiMethod superMethod = superSignature.getMethod();
|
||||
if (visited == null) visited = new THashSet<PsiModifierListOwner>();
|
||||
if (!visited.add(superMethod)) continue;
|
||||
if (!resolveHelper.isAccessible(superMethod, owner, null)) continue;
|
||||
PsiParameter[] superParameters = superMethod.getParameterList().getParameters();
|
||||
if (index < superParameters.length) {
|
||||
annotations = ArrayUtil.mergeArrays(annotations, getAllAnnotations(superParameters[index], inHierarchy, visited));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return annotations;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* User: anna
|
||||
* Date: 26-Jun-2007
|
||||
*/
|
||||
package com.intellij.codeInsight;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.NotNullLazyKey;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class ExternalAnnotationsManager {
|
||||
@NonNls public static final String ANNOTATIONS_XML = "annotations.xml";
|
||||
|
||||
public enum AnnotationPlace {
|
||||
IN_CODE,
|
||||
EXTERNAL,
|
||||
NOWHERE
|
||||
}
|
||||
|
||||
private static final NotNullLazyKey<ExternalAnnotationsManager, Project> INSTANCE_KEY = ServiceManager.createLazyKey(ExternalAnnotationsManager.class);
|
||||
|
||||
public static ExternalAnnotationsManager getInstance(@NotNull Project project) {
|
||||
return INSTANCE_KEY.getValue(project);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract PsiAnnotation findExternalAnnotation(@NotNull PsiModifierListOwner listOwner, @NotNull String annotationFQN);
|
||||
|
||||
@Nullable
|
||||
public abstract PsiAnnotation[] findExternalAnnotations(@NotNull PsiModifierListOwner listOwner);
|
||||
|
||||
public abstract void annotateExternally(@NotNull PsiModifierListOwner listOwner,
|
||||
@NotNull String annotationFQName,
|
||||
@NotNull PsiFile fromFile,
|
||||
PsiNameValuePair[] value);
|
||||
|
||||
public abstract boolean deannotate(@NotNull PsiModifierListOwner listOwner, @NotNull String annotationFQN);
|
||||
|
||||
public abstract AnnotationPlace chooseAnnotationsPlace(@NotNull PsiElement element);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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;
|
||||
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.DefaultJDOMExternalizer;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.JDOMExternalizableStringList;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: 1/25/11
|
||||
*/
|
||||
@State(
|
||||
name = "NullableNotNullManager",
|
||||
storages = {@Storage( file = StoragePathMacros.PROJECT_FILE)}
|
||||
)
|
||||
public class NullableNotNullManager implements PersistentStateComponent<Element> {
|
||||
private static final Logger LOG = Logger.getInstance("#" + NullableNotNullManager.class.getName());
|
||||
|
||||
public String myDefaultNullable = AnnotationUtil.NULLABLE;
|
||||
public String myDefaultNotNull = AnnotationUtil.NOT_NULL;
|
||||
public final JDOMExternalizableStringList myNullables = new JDOMExternalizableStringList();
|
||||
public final JDOMExternalizableStringList myNotNulls = new JDOMExternalizableStringList();
|
||||
|
||||
public static final String[] DEFAULT_NULLABLES = {AnnotationUtil.NULLABLE, "javax.annotation.Nullable", "edu.umd.cs.findbugs.annotations.Nullable"};
|
||||
public static final String[] DEFAULT_NOT_NULLS = {AnnotationUtil.NOT_NULL, "javax.annotation.Nonnull", "edu.umd.cs.findbugs.annotations.NonNull"};
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
|
||||
public static NullableNotNullManager getInstance(Project project) {
|
||||
return ServiceManager.getService(project, NullableNotNullManager.class);
|
||||
}
|
||||
|
||||
public Collection<String> getAllAnnotations() {
|
||||
final List<String> all = new ArrayList<String>(getNullables());
|
||||
all.addAll(getNotNulls());
|
||||
return all;
|
||||
}
|
||||
|
||||
private static void addAllIfNotPresent(Collection<String> collection, String... annotations) {
|
||||
for (String annotation : annotations) {
|
||||
LOG.assertTrue(annotation != null);
|
||||
if (!collection.contains(annotation)) {
|
||||
collection.add(annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setNotNulls(String[] annotations) {
|
||||
myNotNulls.clear();
|
||||
addAllIfNotPresent(myNotNulls, DEFAULT_NOT_NULLS);
|
||||
addAllIfNotPresent(myNotNulls, annotations);
|
||||
}
|
||||
|
||||
public void setNullables(String[] annotations) {
|
||||
myNullables.clear();
|
||||
addAllIfNotPresent(myNullables, DEFAULT_NULLABLES);
|
||||
addAllIfNotPresent(myNullables, annotations);
|
||||
}
|
||||
|
||||
public String getDefaultNullable() {
|
||||
return myDefaultNullable;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getNullable(PsiModifierListOwner owner) {
|
||||
for (String nullable : getNullables()) {
|
||||
if (AnnotationUtil.isAnnotated(owner, nullable, false)) return nullable;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setDefaultNullable(@NotNull String defaultNullable) {
|
||||
LOG.assertTrue(getNullables().contains(defaultNullable));
|
||||
myDefaultNullable = defaultNullable;
|
||||
}
|
||||
|
||||
public String getDefaultNotNull() {
|
||||
return myDefaultNotNull;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getNotNull(PsiModifierListOwner owner) {
|
||||
for (String notNull : getNotNulls()) {
|
||||
if (AnnotationUtil.isAnnotated(owner, notNull, false)) return notNull;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setDefaultNotNull(@NotNull String defaultNotNull) {
|
||||
LOG.assertTrue(getNotNulls().contains(defaultNotNull));
|
||||
myDefaultNotNull = defaultNotNull;
|
||||
}
|
||||
|
||||
public boolean isNullable(PsiModifierListOwner owner, boolean checkBases) {
|
||||
return AnnotationUtil.isAnnotated(owner, getNullables(), checkBases);
|
||||
}
|
||||
|
||||
public boolean isNotNull(PsiModifierListOwner owner, boolean checkBases) {
|
||||
return AnnotationUtil.isAnnotated(owner, getNotNulls(), checkBases);
|
||||
}
|
||||
|
||||
public List<String> getNullables() {
|
||||
if (myNullables.isEmpty()) {
|
||||
synchronized (LOCK) {
|
||||
if (myNullables.isEmpty()) {
|
||||
Collections.addAll(myNullables, DEFAULT_NULLABLES);
|
||||
}
|
||||
}
|
||||
}
|
||||
return myNullables;
|
||||
}
|
||||
|
||||
public List<String> getNotNulls() {
|
||||
if (myNotNulls.isEmpty()) {
|
||||
synchronized (LOCK) {
|
||||
if (myNotNulls.isEmpty()) {
|
||||
Collections.addAll(myNotNulls, DEFAULT_NOT_NULLS);
|
||||
}
|
||||
}
|
||||
}
|
||||
return myNotNulls;
|
||||
}
|
||||
|
||||
public boolean hasDefaultValues() {
|
||||
if (DEFAULT_NULLABLES.length != getNullables().size() || DEFAULT_NOT_NULLS.length != getNotNulls().size()) {
|
||||
return false;
|
||||
}
|
||||
if (myDefaultNotNull != AnnotationUtil.NOT_NULL || myDefaultNullable != AnnotationUtil.NULLABLE) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < DEFAULT_NULLABLES.length; i++) {
|
||||
if (!getNullables().get(i).equals(DEFAULT_NULLABLES[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < DEFAULT_NOT_NULLS.length; i++) {
|
||||
if (!getNotNulls().get(i).equals(DEFAULT_NOT_NULLS[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element getState() {
|
||||
final Element component = new Element("component");
|
||||
|
||||
if (hasDefaultValues()) {
|
||||
return component;
|
||||
}
|
||||
|
||||
try {
|
||||
DefaultJDOMExternalizer.writeExternal(this, component);
|
||||
}
|
||||
catch (WriteExternalException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(Element state) {
|
||||
try {
|
||||
DefaultJDOMExternalizer.readExternal(this, state);
|
||||
}
|
||||
catch (InvalidDataException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isNullable(@NotNull PsiModifierListOwner owner) {
|
||||
return !isNotNull(owner) && getInstance(owner.getProject()).isNullable(owner, true);
|
||||
}
|
||||
|
||||
public static boolean isNotNull(@NotNull PsiModifierListOwner owner) {
|
||||
return getInstance(owner.getProject()).isNotNull(owner, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,617 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.NullableNotNullManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.beans.Introspector;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Mike
|
||||
*/
|
||||
public class PropertyUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.util.PropertyUtil");
|
||||
|
||||
private PropertyUtil() {
|
||||
}
|
||||
|
||||
public static boolean isSimplePropertyGetter(PsiMethod method) {
|
||||
return hasGetterName(method) && method.getParameterList().getParametersCount() == 0;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
public static boolean hasGetterName(final PsiMethod method) {
|
||||
if (method == null) return false;
|
||||
|
||||
if (method.isConstructor()) return false;
|
||||
|
||||
String methodName = method.getName();
|
||||
PsiType returnType = method.getReturnType();
|
||||
int methodNameLength = methodName.length();
|
||||
if (methodName.startsWith("get") && methodNameLength > "get".length()) {
|
||||
if (Character.isLowerCase(methodName.charAt("get".length()))
|
||||
&& (methodNameLength == "get".length() + 1 || Character.isLowerCase(methodName.charAt("get".length() + 1)))) {
|
||||
return false;
|
||||
}
|
||||
if (returnType != null && PsiType.VOID.equals(returnType)) return false;
|
||||
}
|
||||
else if (methodName.startsWith("is") && methodNameLength > "is".length()) {
|
||||
if (Character.isLowerCase(methodName.charAt("is".length()))
|
||||
&& (methodNameLength == "is".length() + 1 || Character.isLowerCase(methodName.charAt("is".length() + 1)))) {
|
||||
return false;
|
||||
}
|
||||
return isBoolean(returnType);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("HardCodedStringLiteral")
|
||||
public static boolean isSimplePropertySetter(@Nullable 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()))
|
||||
&& (methodName.length() == "set".length() + 1 || Character.isLowerCase(methodName.charAt("set".length() + 1)))) return false;
|
||||
|
||||
if (method.getParameterList().getParametersCount() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiType returnType = method.getReturnType();
|
||||
|
||||
if (returnType == null || PsiType.VOID.equals(returnType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Comparing.equal(PsiUtil.resolveClassInType(TypeConversionUtil.erasure(returnType)), method.getContainingClass());
|
||||
}
|
||||
|
||||
@Nullable public static String getPropertyName(PsiMethod method) {
|
||||
if (isSimplePropertyGetter(method)) {
|
||||
return getPropertyNameByGetter(method);
|
||||
}
|
||||
else if (isSimplePropertySetter(method)) {
|
||||
return getPropertyNameBySetter(method);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
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));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getPropertyNameBySetter(PsiMethod setterMethod) {
|
||||
String methodName = setterMethod.getName();
|
||||
return Introspector.decapitalize(methodName.substring(3));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Map<String, PsiMethod> getAllProperties(@NotNull final PsiClass psiClass, final boolean acceptSetters, final boolean acceptGetters) {
|
||||
return getAllProperties(psiClass, acceptSetters, acceptGetters, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Map<String, PsiMethod> getAllProperties(@NotNull final PsiClass psiClass, final boolean acceptSetters, final boolean acceptGetters, final boolean includeSuperClass) {
|
||||
final Map<String, PsiMethod> map = new HashMap<String, PsiMethod>();
|
||||
final PsiMethod[] methods = includeSuperClass ? psiClass.getAllMethods() : psiClass.getMethods();
|
||||
|
||||
for (PsiMethod method : methods) {
|
||||
if (filterMethods(method)) continue;
|
||||
if (acceptSetters && isSimplePropertySetter(method)||
|
||||
acceptGetters && isSimplePropertyGetter(method)) {
|
||||
map.put(getPropertyName(method), method);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
private static boolean filterMethods(final PsiMethod method) {
|
||||
if(method.hasModifierProperty(PsiModifier.STATIC) || !method.hasModifierProperty(PsiModifier.PUBLIC)) return true;
|
||||
|
||||
PsiClass psiClass = method.getContainingClass();
|
||||
if (psiClass == null) return false;
|
||||
final String className = psiClass.getQualifiedName();
|
||||
return className != null && className.equals(CommonClassNames.JAVA_LANG_OBJECT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<PsiMethod> getSetters(@NotNull final PsiClass psiClass, final String propertyName) {
|
||||
final String setterName = suggestSetterName(propertyName);
|
||||
final PsiMethod[] psiMethods = psiClass.findMethodsByName(setterName, true);
|
||||
final ArrayList<PsiMethod> list = new ArrayList<PsiMethod>(psiMethods.length);
|
||||
for (PsiMethod method : psiMethods) {
|
||||
if (filterMethods(method)) continue;
|
||||
if (isSimplePropertySetter(method)) {
|
||||
list.add(method);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<PsiMethod> getGetters(@NotNull final PsiClass psiClass, final String propertyName) {
|
||||
final String[] names = suggestGetterNames(propertyName);
|
||||
final ArrayList<PsiMethod> list = new ArrayList<PsiMethod>();
|
||||
for (String name : names) {
|
||||
final PsiMethod[] psiMethods = psiClass.findMethodsByName(name, true);
|
||||
for (PsiMethod method : psiMethods) {
|
||||
if (filterMethods(method)) continue;
|
||||
if (isSimplePropertyGetter(method)) {
|
||||
list.add(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@NotNull
|
||||
public static List<PsiMethod> getAccessors(@NotNull final PsiClass psiClass, final String propertyName) {
|
||||
return ContainerUtil.concat(getGetters(psiClass, propertyName), getSetters(psiClass, propertyName));
|
||||
}
|
||||
|
||||
@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) {
|
||||
return StringUtil.getPropertyName(methodName);
|
||||
}
|
||||
|
||||
public static String suggestGetterName(@NonNls @NotNull String propertyName, @Nullable PsiType propertyType) {
|
||||
return suggestGetterName(propertyName, propertyType, null);
|
||||
}
|
||||
|
||||
public static String suggestGetterName(@NotNull String propertyName, @Nullable PsiType propertyType, @NonNls String existingGetterName) {
|
||||
@NonNls StringBuffer name = new StringBuffer(StringUtil.capitalizeWithJavaBeanConvention(propertyName));
|
||||
if (isBoolean(propertyType)) {
|
||||
if (existingGetterName == null || !existingGetterName.startsWith("get")) {
|
||||
name.insert(0, "is");
|
||||
}
|
||||
else {
|
||||
name.insert(0, "get");
|
||||
}
|
||||
}
|
||||
else {
|
||||
name.insert(0, "get");
|
||||
}
|
||||
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
private static boolean isBoolean(@Nullable PsiType propertyType) {
|
||||
return PsiType.BOOLEAN.equals(propertyType);
|
||||
}
|
||||
|
||||
@NonNls
|
||||
public static String[] suggestGetterNames(String propertyName) {
|
||||
final String str = StringUtil.capitalizeWithJavaBeanConvention(propertyName);
|
||||
return new String[] { "is" + str, "get" + str };
|
||||
}
|
||||
|
||||
public static String suggestSetterName(@NonNls String propertyName) {
|
||||
@NonNls StringBuffer name = new StringBuffer(StringUtil.capitalizeWithJavaBeanConvention(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 (CommonClassNames.JAVA_LANG_OBJECT.equals(method.getContainingClass().getQualifiedName())) continue;
|
||||
|
||||
if (isSimplePropertyGetter(method)) {
|
||||
result.add(getPropertyName(method));
|
||||
}
|
||||
}
|
||||
|
||||
return ArrayUtil.toStringArray(result);
|
||||
}
|
||||
|
||||
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 (CommonClassNames.JAVA_LANG_OBJECT.equals(method.getContainingClass().getQualifiedName())) continue;
|
||||
|
||||
if (isSimplePropertySetter(method)) {
|
||||
result.add(getPropertyName(method));
|
||||
}
|
||||
}
|
||||
|
||||
return ArrayUtil.toStringArray(result);
|
||||
}
|
||||
|
||||
public static PsiMethod generateGetterPrototype(@NotNull PsiField field) {
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(field.getProject()).getElementFactory();
|
||||
Project project = field.getProject();
|
||||
String name = field.getName();
|
||||
String getName = suggestGetterName(project, field);
|
||||
try {
|
||||
PsiMethod getMethod = factory.createMethod(getName, field.getType());
|
||||
PsiUtil.setModifierProperty(getMethod, PsiModifier.PUBLIC, true);
|
||||
if (field.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
PsiUtil.setModifierProperty(getMethod, 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) {
|
||||
return generateSetterPrototype(field, containingClass, false);
|
||||
}
|
||||
|
||||
public static PsiMethod generateSetterPrototype(PsiField field, final PsiClass containingClass, boolean returnSelf) {
|
||||
Project project = field.getProject();
|
||||
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(field.getProject()).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, returnSelf ? factory.createType(containingClass) : PsiType.VOID);
|
||||
String parameterName = codeStyleManager.propertyNameToVariableName(propertyName, VariableKind.PARAMETER);
|
||||
PsiParameter param = factory.createParameter(parameterName, field.getType());
|
||||
|
||||
annotateWithNullableStuff(field, factory, param);
|
||||
|
||||
setMethod.getParameterList().add(param);
|
||||
PsiUtil.setModifierProperty(setMethod, PsiModifier.PUBLIC, true);
|
||||
PsiUtil.setModifierProperty(setMethod, 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");
|
||||
if (returnSelf) {
|
||||
buffer.append("return this;\n");
|
||||
}
|
||||
buffer.append("}");
|
||||
PsiCodeBlock body = factory.createCodeBlockFromText(buffer.toString(), null);
|
||||
setMethod.getBody().replace(body);
|
||||
setMethod = (PsiMethod)CodeStyleManager.getInstance(project).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 {
|
||||
final NullableNotNullManager manager = NullableNotNullManager.getInstance(field.getProject());
|
||||
final String notNull = manager.getNotNull(field);
|
||||
if (notNull != null) {
|
||||
annotate(factory, listOwner, notNull);
|
||||
}
|
||||
else {
|
||||
final String nullable = manager.getNullable(field);
|
||||
if (nullable != null) {
|
||||
annotate(factory, listOwner, 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) {
|
||||
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.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;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiField findPropertyFieldByMember(final PsiMember psiMember) {
|
||||
if (psiMember instanceof PsiField) {
|
||||
return (PsiField)psiMember;
|
||||
}
|
||||
else if (psiMember instanceof PsiMethod) {
|
||||
final PsiMethod psiMethod = (PsiMethod)psiMember;
|
||||
final PsiType returnType = psiMethod.getReturnType();
|
||||
if (returnType == null) return null;
|
||||
final PsiCodeBlock body = psiMethod.getBody();
|
||||
final PsiStatement[] statements = body == null? null : body.getStatements();
|
||||
final PsiStatement statement = statements == null || statements.length != 1? null : statements[0];
|
||||
final PsiElement target;
|
||||
if (PsiType.VOID.equals(returnType)) {
|
||||
final PsiExpression expression =
|
||||
statement instanceof PsiExpressionStatement ? ((PsiExpressionStatement)statement).getExpression() : null;
|
||||
target = expression instanceof PsiAssignmentExpression ? ((PsiAssignmentExpression)expression).getLExpression() : null;
|
||||
}
|
||||
else {
|
||||
target = statement instanceof PsiReturnStatement ? ((PsiReturnStatement)statement).getReturnValue() : null;
|
||||
}
|
||||
final PsiElement resolved = target instanceof PsiReferenceExpression ? ((PsiReferenceExpression)target).resolve() : null;
|
||||
if (resolved instanceof PsiField) {
|
||||
final PsiField field = (PsiField)resolved;
|
||||
if (psiMember.getContainingClass() == field.getContainingClass() ||
|
||||
psiMember.getContainingClass().isInheritor(field.getContainingClass(), true)) return field;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user