@Nullable public static PsiClass getSuperClass(@NotNull PsiClass psiClass) { PsiManager manager = psiClass.getManager(); GlobalSearchScope resolveScope = psiClass.getResolveScope(); final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject()); if (psiClass.isInterface()) { return facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope); } if (psiClass.isEnum()) { return facade.findClass(CommonClassNames.JAVA_LANG_ENUM, resolveScope); } if (psiClass instanceof PsiAnonymousClass) { PsiClassType baseClassReference = ((PsiAnonymousClass) psiClass).getBaseClassType(); PsiClass baseClass = baseClassReference.resolve(); if (baseClass == null || baseClass.isInterface()) return facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope); return baseClass; } if (CommonClassNames.JAVA_LANG_OBJECT.equals(psiClass.getQualifiedName())) return null; final PsiClassType[] referenceElements = psiClass.getExtendsListTypes(); if (referenceElements.length == 0) return facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope); PsiClass psiResoved = referenceElements[0].resolve(); return psiResoved == null ? facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope) : psiResoved; }
@NotNull public static PsiClass[] getInterfaces(@NotNull PsiClass psiClass) { if (psiClass.isInterface()) { final PsiClassType[] extendsListTypes = psiClass.getExtendsListTypes(); return resolveClassReferenceList( extendsListTypes, psiClass.getManager(), psiClass.getResolveScope(), false); } if (psiClass instanceof PsiAnonymousClass) { PsiClassType baseClassReference = ((PsiAnonymousClass) psiClass).getBaseClassType(); PsiClass baseClass = baseClassReference.resolve(); return baseClass != null && baseClass.isInterface() ? new PsiClass[] {baseClass} : PsiClass.EMPTY_ARRAY; } final PsiClassType[] implementsListTypes = psiClass.getImplementsListTypes(); return resolveClassReferenceList( implementsListTypes, psiClass.getManager(), psiClass.getResolveScope(), false); }
@NotNull public static PsiClassType createListType(@NotNull PsiClass elements) { JavaPsiFacade facade = JavaPsiFacade.getInstance(elements.getProject()); GlobalSearchScope resolveScope = elements.getResolveScope(); PsiClass listClass = facade.findClass(JAVA_UTIL_LIST, resolveScope); if (listClass == null) { return facade.getElementFactory().createTypeByFQClassName(JAVA_UTIL_LIST, resolveScope); } return facade .getElementFactory() .createType(listClass, facade.getElementFactory().createType(elements)); }
@Override public ProblemDescriptor[] checkClass( @NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) { final Project project = aClass.getProject(); final PsiIdentifier nameIdentifier = aClass.getNameIdentifier(); final Module module = ModuleUtilCore.findModuleForPsiElement(aClass); if (nameIdentifier == null || module == null || !PsiUtil.isInstantiable(aClass)) return null; final PsiClass base = JavaPsiFacade.getInstance(project).findClass(getClassName(), aClass.getResolveScope()); if (base == null || !aClass.isInheritor(base, true)) return null; String descriptionDir = DescriptionCheckerUtil.getDescriptionDirName(aClass); if (StringUtil.isEmptyOrSpaces(descriptionDir)) { return null; } for (PsiDirectory description : getDescriptionsDirs(module)) { PsiDirectory dir = description.findSubdirectory(descriptionDir); if (dir == null) continue; final PsiFile descr = dir.findFile("description.html"); if (descr != null) { if (!hasBeforeAndAfterTemplate(dir.getVirtualFile())) { PsiElement problem = aClass.getNameIdentifier(); ProblemDescriptor problemDescriptor = manager.createProblemDescriptor( problem == null ? nameIdentifier : problem, getHasNotBeforeAfterError(), isOnTheFly, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false); return new ProblemDescriptor[] {problemDescriptor}; } return null; } } final PsiElement problem = aClass.getNameIdentifier(); final ProblemDescriptor problemDescriptor = manager.createProblemDescriptor( problem == null ? nameIdentifier : problem, getHasNotDescriptionError(), isOnTheFly, new LocalQuickFix[] {getFix(module, descriptionDir)}, ProblemHighlightType.GENERIC_ERROR_OR_WARNING); return new ProblemDescriptor[] {problemDescriptor}; }
@NotNull public static PsiClassType[] getSuperTypes(@NotNull PsiClass psiClass) { if (psiClass instanceof PsiAnonymousClass) { PsiClassType baseClassType = ((PsiAnonymousClass) psiClass).getBaseClassType(); PsiClass baseClass = baseClassType.resolve(); if (baseClass == null || !baseClass.isInterface()) { return new PsiClassType[] {baseClassType}; } else { PsiClassType objectType = PsiType.getJavaLangObject(psiClass.getManager(), psiClass.getResolveScope()); return new PsiClassType[] {objectType, baseClassType}; } } PsiClassType[] extendsTypes = psiClass.getExtendsListTypes(); PsiClassType[] implementsTypes = psiClass.getImplementsListTypes(); boolean hasExtends = extendsTypes.length != 0; int extendsListLength = extendsTypes.length + (hasExtends ? 0 : 1); PsiClassType[] result = new PsiClassType[extendsListLength + implementsTypes.length]; System.arraycopy(extendsTypes, 0, result, 0, extendsTypes.length); if (!hasExtends) { if (CommonClassNames.JAVA_LANG_OBJECT.equals(psiClass.getQualifiedName())) { return PsiClassType.EMPTY_ARRAY; } PsiManager manager = psiClass.getManager(); PsiClassType objectType = PsiType.getJavaLangObject(manager, psiClass.getResolveScope()); result[0] = objectType; } System.arraycopy(implementsTypes, 0, result, extendsListLength, implementsTypes.length); for (int i = 0; i < result.length; i++) { PsiClassType type = result[i]; result[i] = (PsiClassType) PsiUtil.captureToplevelWildcards(type, psiClass); } return result; }
@Override public Result calculateResult(@NotNull Expression[] params, ExpressionContext context) { if (params.length != 1) return null; final Result result = params[0].calculateResult(context); if (result == null) return null; Project project = context.getProject(); PsiExpression expr = MacroUtil.resultToPsiExpression(result, context); if (expr == null) return null; PsiType type = expr.getType(); if (type instanceof PsiArrayType) { return new PsiTypeResult(((PsiArrayType) type).getComponentType(), project); } if (type instanceof PsiClassType) { PsiClassType.ClassResolveResult resolveResult = ((PsiClassType) type).resolveGenerics(); PsiClass aClass = resolveResult.getElement(); if (aClass != null) { PsiClass iterableClass = JavaPsiFacade.getInstance(project) .findClass("java.lang.Iterable", aClass.getResolveScope()); if (iterableClass != null) { PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor( iterableClass, aClass, resolveResult.getSubstitutor()); if (substitutor != null) { PsiType parameterType = substitutor.substitute(iterableClass.getTypeParameters()[0]); if (parameterType instanceof PsiCapturedWildcardType) { parameterType = ((PsiCapturedWildcardType) parameterType).getWildcard(); } if (parameterType != null) { if (parameterType instanceof PsiWildcardType) { if (((PsiWildcardType) parameterType).isExtends()) { return new PsiTypeResult(((PsiWildcardType) parameterType).getBound(), project); } else return null; } return new PsiTypeResult(parameterType, project); } } } } } return null; }
@NotNull private static PsiClass[] getSupersInner(@NotNull PsiClass psiClass) { PsiClassType[] extendsListTypes = psiClass.getExtendsListTypes(); PsiClassType[] implementsListTypes = psiClass.getImplementsListTypes(); if (psiClass.isInterface()) { return resolveClassReferenceList( extendsListTypes, psiClass.getManager(), psiClass.getResolveScope(), true); } if (psiClass instanceof PsiAnonymousClass) { PsiAnonymousClass psiAnonymousClass = (PsiAnonymousClass) psiClass; PsiClassType baseClassReference = psiAnonymousClass.getBaseClassType(); PsiClass baseClass = baseClassReference.resolve(); if (baseClass != null) { if (baseClass.isInterface()) { PsiClass objectClass = JavaPsiFacade.getInstance(psiClass.getProject()) .findClass(CommonClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope()); return objectClass != null ? new PsiClass[] {objectClass, baseClass} : new PsiClass[] {baseClass}; } return new PsiClass[] {baseClass}; } PsiClass objectClass = JavaPsiFacade.getInstance(psiClass.getProject()) .findClass(CommonClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope()); return objectClass != null ? new PsiClass[] {objectClass} : PsiClass.EMPTY_ARRAY; } if (psiClass instanceof PsiTypeParameter) { if (extendsListTypes.length == 0) { final PsiClass objectClass = JavaPsiFacade.getInstance(psiClass.getProject()) .findClass(CommonClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope()); return objectClass != null ? new PsiClass[] {objectClass} : PsiClass.EMPTY_ARRAY; } return resolveClassReferenceList( extendsListTypes, psiClass.getManager(), psiClass.getResolveScope(), false); } PsiClass[] interfaces = resolveClassReferenceList( implementsListTypes, psiClass.getManager(), psiClass.getResolveScope(), false); PsiClass superClass = getSuperClass(psiClass); if (superClass == null) return interfaces; PsiClass[] types = new PsiClass[interfaces.length + 1]; types[0] = superClass; System.arraycopy(interfaces, 0, types, 1, interfaces.length); return types; }
private static boolean isRunnable(final PsiClass psiClass) { if (!(psiClass instanceof GrTypeDefinition)) return false; if (psiClass instanceof PsiAnonymousClass) return false; if (psiClass.isInterface()) return false; final PsiClass runnable = JavaPsiFacade.getInstance(psiClass.getProject()) .findClass("java.lang.Runnable", psiClass.getResolveScope()); if (runnable == null) return false; final PsiMethod runMethod = runnable.getMethods()[0]; final PsiMethod[] runImplementations = psiClass.findMethodsBySignature(runMethod, false); if (runImplementations.length == 1 && runImplementations[0] instanceof GrMethod && ((GrMethod) runImplementations[0]).getBlock() != null) { return psiClass.getContainingClass() == null || psiClass.hasModifierProperty(PsiModifier.STATIC); } return false; }
private static PsiClassType getEnumSuperType( @NotNull PsiClass psiClass, @NotNull PsiElementFactory factory) { PsiClassType superType; final PsiManager manager = psiClass.getManager(); final PsiClass enumClass = JavaPsiFacade.getInstance(manager.getProject()) .findClass("java.lang.Enum", psiClass.getResolveScope()); if (enumClass == null) { try { superType = (PsiClassType) factory.createTypeFromText("java.lang.Enum", null); } catch (IncorrectOperationException e) { superType = null; } } else { final PsiTypeParameter[] typeParameters = enumClass.getTypeParameters(); PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; if (typeParameters.length == 1) { substitutor = substitutor.put(typeParameters[0], factory.createType(psiClass)); } superType = new PsiImmediateClassType(enumClass, substitutor); } return superType; }
static boolean isSideEffectFreeConstructor(PsiNewExpression newExpression) { PsiJavaCodeReferenceElement classReference = newExpression.getClassReference(); PsiClass aClass = classReference == null ? null : (PsiClass) classReference.resolve(); String qualifiedName = aClass == null ? null : aClass.getQualifiedName(); if (qualifiedName == null) return false; if (ourSideEffectFreeClasses.contains(qualifiedName)) return true; PsiFile file = aClass.getContainingFile(); PsiDirectory directory = file.getContainingDirectory(); PsiPackage classPackage = JavaDirectoryService.getInstance().getPackage(directory); String packageName = classPackage == null ? null : classPackage.getQualifiedName(); // all Throwable descendants from java.lang are side effects free if ("java.lang".equals(packageName) || "java.io".equals(packageName)) { PsiClass throwableClass = JavaPsiFacade.getInstance(aClass.getProject()) .findClass("java.lang.Throwable", aClass.getResolveScope()); if (throwableClass != null && InheritanceUtil.isInheritorOrSelf(aClass, throwableClass, true)) { return true; } } return false; }
@Override @NotNull public GlobalSearchScope getResolveScope() { return myClass.getResolveScope(); }
private void generatorLayoutCode(String contextName, String findPre) { List<Element> editTextElements = new ArrayList<>(); List<Element> clickableElements = new ArrayList<>(); List<Element> itemClickableElements = new ArrayList<>(); // generator findViewById code in initView() method StringBuilder initView = new StringBuilder(); if (TextUtils.isEmpty(findPre)) { initView.append("private void initView() {\n"); } else { initView.append("private void initView(View " + findPre + ") {\n"); } for (Element element : mElements) { String pre = TextUtils.isEmpty(findPre) ? "" : findPre + "."; initView.append( element.getFieldName() + " = (" + element.name + ") " + pre + "findViewById(" + element.getFullID() + ");\n"); // set flag if (element.isEditText) { editTextElements.add(element); } if (element.isClickable) { clickableElements.add(element); } if (element.isItemClickable) { itemClickableElements.add(element); } } // generator EditText validate code if need StringBuilder sbEditText = new StringBuilder(); if (editTextElements.size() > 0) { sbEditText.append("private void submit() {\n"); sbEditText.append("\t\t// validate\n"); for (Element element : editTextElements) { // generator EditText string name String idName = element.id; int index = idName.lastIndexOf("_"); String name = index == -1 ? idName : idName.substring(index + 1); if (name.equals(idName)) { name += "String"; } sbEditText.append("String " + name + " = " + idName + ".getText().toString().trim();\n"); sbEditText.append("if(TextUtils.isEmpty(" + name + ")) {\n"); // 提示的toast为EditText的hint文字,无hint时格式为"name不能为空" String emptyTint = name + "不能为空"; String hint = element.xml.getAttributeValue("android:hint"); if (!TextUtils.isEmpty(hint) && !hint.startsWith("@string")) { emptyTint = hint; } sbEditText.append( "Toast.makeText(" + contextName + ", \"" + emptyTint + "\", Toast.LENGTH_SHORT).show();\n"); sbEditText.append("return;\n"); sbEditText.append("}\n"); sbEditText.append("\n"); } sbEditText.append("\t\t// TODO validate success, do something\n"); sbEditText.append("\n\n}\n"); } // generator clickable code if need StringBuilder sbClickable = new StringBuilder(); if (clickableElements.size() > 0) { // let class implement OnClickListener PsiReferenceList implementsList = mClass.getImplementsList(); if (implementsList != null) { PsiJavaCodeReferenceElement[] referenceElements = implementsList.getReferenceElements(); boolean hasImpl = false; for (PsiJavaCodeReferenceElement re : referenceElements) { hasImpl = re.getText().contains("OnClickListener"); } // add implement if not exist if (!hasImpl) { PsiJavaCodeReferenceElement pjcre = mFactory.createReferenceElementByFQClassName( "android.view.View.OnClickListener", mClass.getResolveScope()); implementsList.add(pjcre); } } initView.append("\n"); sbClickable .append("@Override public void onClick(View v) {\n") .append("switch (v.getId()) {\n"); for (Element element : clickableElements) { // generator setOnClickListener code in initView() initView.append(element.getFieldName() + ".setOnClickListener(this);\n"); // generator override public void onClick(View v) method sbClickable.append("case " + element.getFullID() + " :\n\nbreak;\n"); } sbClickable.append("}\n}"); } // generator itemClickable code if need for (Element element : itemClickableElements) { // generator setOnClickListener code in initView() initView.append( element.getFieldName() + ".setOnItemClickListener(new AdapterView.OnItemClickListener() {\n"); initView.append("@Override\n"); initView.append( "public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n\n"); initView.append("}\n"); initView.append("});\n"); } initView.append("}\n"); PsiMethod[] initViewMethods = mClass.findMethodsByName("initView", false); if (initViewMethods.length > 0 && initViewMethods[0].getBody() != null) { // already have method // append non-repeated field PsiCodeBlock initViewMethodBody = initViewMethods[0].getBody(); for (Element element : mElements) { // append findViewById String pre = TextUtils.isEmpty(findPre) ? "" : findPre + "."; String s2 = element.getFieldName() + " = (" + element.name + ") " + pre + "findViewById(" + element.getFullID() + ");"; initViewMethodBody.add(mFactory.createStatementFromText(s2, initViewMethods[0])); // append setOnClickListener String s1 = element.getFieldName() + ".setOnClickListener(this);"; initViewMethodBody.add(mFactory.createStatementFromText(s1, initViewMethods[0])); } } else { // new method mClass.add(mFactory.createMethodFromText(initView.toString(), mClass)); } if (clickableElements.size() > 0) { PsiMethod[] onClickMethods = mClass.findMethodsByName("onClick", false); if (onClickMethods.length > 0 && onClickMethods[0].getBody() != null) { // already have method // append non-repeated field PsiCodeBlock onClickMethodBody = onClickMethods[0].getBody(); for (PsiElement element : onClickMethodBody.getChildren()) { if (element instanceof PsiSwitchStatement) { PsiSwitchStatement switchStatement = (PsiSwitchStatement) element; PsiCodeBlock body = switchStatement.getBody(); if (body != null) { for (Element clickableElement : clickableElements) { String caseStr = "case " + clickableElement.getFullID() + " :"; body.add(mFactory.createStatementFromText(caseStr, body)); body.add(mFactory.createStatementFromText("break;", body)); } } break; } } } else { // new method mClass.add(mFactory.createMethodFromText(sbClickable.toString(), mClass)); } } if (editTextElements.size() > 0) { mClass.add(mFactory.createMethodFromText(sbEditText.toString(), mClass)); } }
@NotNull private static PsiClassType getAnnotationSuperType( @NotNull PsiClass psiClass, @NotNull PsiElementFactory factory) { return factory.createTypeByFQClassName( "java.lang.annotation.Annotation", psiClass.getResolveScope()); }
private static PsiMethod generateDelegateMethod( PsiMethod method, PsiClass superClass, PsiSubstitutor substitutor, boolean keepParameterAnnotations) { final LightMethodBuilder builder = new LightMethodBuilder( superClass.getManager(), GroovyFileType.GROOVY_LANGUAGE, method.getName()); builder.setContainingClass(superClass); builder.setMethodReturnType(substitutor.substitute(method.getReturnType())); builder.setNavigationElement(method); builder.addModifier(PsiModifier.PUBLIC); final PsiTypeParameter[] typeParameters = method.getTypeParameters(); final PsiClass containingClass = method.getContainingClass(); boolean isRaw = containingClass != null && PsiUtil.isRawSubstitutor(containingClass, substitutor); if (isRaw) { substitutor = JavaPsiFacade.getInstance(method.getProject()) .getElementFactory() .createRawSubstitutor(substitutor, typeParameters); } if (!isRaw) { for (PsiTypeParameter typeParameter : typeParameters) { builder.addTypeParameter(typeParameter); } } final PsiParameter[] originalParameters = method.getParameterList().getParameters(); for (int i = 0; i < originalParameters.length; i++) { PsiParameter originalParameter = originalParameters[i]; PsiType type; if (isRaw) { type = TypeConversionUtil.erasure(substitutor.substitute(originalParameter.getType())); } else { type = substitutor.substitute(originalParameter.getType()); } if (type == null) { type = PsiType.getJavaLangObject(superClass.getManager(), superClass.getResolveScope()); } final LightParameter lightParameter = new LightParameter( StringUtil.notNullize(originalParameter.getName(), "p" + i), type, builder, JavaLanguage.INSTANCE); if (keepParameterAnnotations) { final PsiCompositeModifierList delegatingModifierList = new PsiCompositeModifierList( method.getManager(), Collections.singletonList(originalParameter.getModifierList())); lightParameter.setModifierList(delegatingModifierList); } builder.addParameter(lightParameter); } builder.setBaseIcon(JetgroovyIcons.Groovy.Method); return new DelegatedMethod(builder, method); }