/* * 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 org.jetbrains.idea.devkit.util; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.GlobalSearchScopesCore; import com.intellij.ui.components.JBList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * @author Konstantin Bulenkov */ public class PsiUtil { private static final Key IDEA_PROJECT = Key.create("idea.internal.inspections.enabled"); private static final String IDE_PROJECT_MARKER_CLASS = JBList.class.getName(); public static final PsiElementVisitor EMPTY_VISITOR = new PsiElementVisitor() { }; private PsiUtil() { } public static boolean isInstantiable(@NotNull PsiClass cls) { final PsiModifierList modList = cls.getModifierList(); if (modList == null || cls.isInterface() || modList.hasModifierProperty(PsiModifier.ABSTRACT) || !isPublicOrStaticInnerClass(cls)) { return false; } final PsiMethod[] constructors = cls.getConstructors(); if (constructors.length == 0) return true; for (PsiMethod constructor : constructors) { if (constructor.getParameterList().getParameters().length == 0 && constructor.hasModifierProperty(PsiModifier.PUBLIC)) { return true; } } return false; } public static boolean isPublicOrStaticInnerClass(@NotNull PsiClass cls) { final PsiModifierList modifiers = cls.getModifierList(); if (modifiers == null) return false; return modifiers.hasModifierProperty(PsiModifier.PUBLIC) && (cls.getParent() instanceof PsiFile || modifiers.hasModifierProperty(PsiModifier.STATIC)); } @Nullable public static String getReturnedLiteral(PsiMethod method, PsiClass cls) { final PsiExpression value = getReturnedExpression(method); if (value instanceof PsiLiteralExpression) { final Object str = ((PsiLiteralExpression)value).getValue(); return str == null ? null : str.toString(); } else if (value instanceof PsiMethodCallExpression) { if (isSimpleClassNameExpression((PsiMethodCallExpression)value)) { return cls.getName(); } } return null; } private static boolean isSimpleClassNameExpression(PsiMethodCallExpression expr) { String text = expr.getText(); if (text == null) return false; text = text.replaceAll(" ", "") .replaceAll("\n", "") .replaceAll("\t", "") .replaceAll("\r", ""); return "getClass().getSimpleName()".equals(text) || "this.getClass().getSimpleName()".equals(text); } @Nullable public static PsiExpression getReturnedExpression(PsiMethod method) { PsiCodeBlock body = method.getBody(); if (body != null) { PsiStatement[] statements = body.getStatements(); if (statements.length == 1 && statements[0] instanceof PsiReturnStatement) { return ((PsiReturnStatement)statements[0]).getReturnValue(); } } return null; } @Nullable public static PsiMethod findNearestMethod(String name, @Nullable PsiClass cls) { if (cls == null) return null; for (PsiMethod method : cls.getMethods()) { if (method.getParameterList().getParametersCount() == 0 && method.getName().equals(name)) { return method.getModifierList().hasModifierProperty(PsiModifier.ABSTRACT) ? null : method; } } return findNearestMethod(name, cls.getSuperClass()); } public static boolean isIdeaProject(@Nullable Project project) { if (project == null) return false; Boolean flag = project.getUserData(IDEA_PROJECT); if (flag == null) { flag = checkIdeaProject(project); project.putUserData(IDEA_PROJECT, flag); } return flag; } public static boolean isPluginProject(Project project) { return JavaPsiFacade.getInstance(project).findClass(IDE_PROJECT_MARKER_CLASS, GlobalSearchScope.allScope(project)) != null; } private static boolean isIntelliJBasedDir(VirtualFile baseDir) { if (baseDir == null) { return false; } for (VirtualFile dir : new VirtualFile[]{baseDir, baseDir.findChild("community")}) { if (dir == null || !dir.isDirectory()) { continue; } if (dir.findChild("idea.iml") != null || dir.findChild("community-main.iml") != null) { return true; } } return false; } private static boolean checkIdeaProject(@NotNull Project project) { if (!isIntelliJBasedDir(project.getBaseDir())) { return false; } GlobalSearchScope scope = GlobalSearchScopesCore.projectProductionScope(project); if (JavaPsiFacade.getInstance(project).findClass(IDE_PROJECT_MARKER_CLASS, scope) == null) { return false; } return true; } }