private static PsiSubstitutor obtainFinalSubstitutor( PsiClass superClass, PsiSubstitutor superSubstitutor, PsiSubstitutor derivedSubstitutor, boolean inRawContext) { if (inRawContext) { Set<PsiTypeParameter> typeParams = superSubstitutor.getSubstitutionMap().keySet(); PsiElementFactory factory = JavaPsiFacade.getElementFactory(superClass.getProject()); superSubstitutor = factory.createRawSubstitutor( derivedSubstitutor, typeParams.toArray(new PsiTypeParameter[typeParams.size()])); } Map<PsiTypeParameter, PsiType> map = null; for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(superClass)) { PsiType type = superSubstitutor.substitute(typeParameter); final PsiType t = derivedSubstitutor.substitute(type); if (map == null) { map = new THashMap<PsiTypeParameter, PsiType>(); } map.put(typeParameter, t); } return map == null ? PsiSubstitutor.EMPTY : JavaPsiFacade.getInstance(superClass.getProject()) .getElementFactory() .createSubstitutor(map); }
private static void addDefaultConstructor( JavaChangeInfo changeInfo, PsiClass aClass, final UsageInfo[] usages) throws IncorrectOperationException { if (!(aClass instanceof PsiAnonymousClass)) { PsiElementFactory factory = JavaPsiFacade.getElementFactory(aClass.getProject()); PsiMethod defaultConstructor = factory.createMethodFromText(aClass.getName() + "(){}", aClass); defaultConstructor = (PsiMethod) CodeStyleManager.getInstance(aClass.getProject()).reformat(defaultConstructor); defaultConstructor = (PsiMethod) aClass.add(defaultConstructor); PsiUtil.setModifierProperty( defaultConstructor, VisibilityUtil.getVisibilityModifier(aClass.getModifierList()), true); addSuperCall(changeInfo, defaultConstructor, null, usages); } else { final PsiElement parent = aClass.getParent(); if (parent instanceof PsiNewExpression) { final PsiExpressionList argumentList = ((PsiNewExpression) parent).getArgumentList(); final PsiClass baseClass = changeInfo.getMethod().getContainingClass(); final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, aClass, PsiSubstitutor.EMPTY); fixActualArgumentsList(argumentList, changeInfo, true, substitutor); } } }
@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 void putInMap( PsiClass aClass, Map<MethodSignature, HierarchicalMethodSignature> result, Map<MethodSignature, HierarchicalMethodSignatureImpl> map, HierarchicalMethodSignature hierarchicalMethodSignature, MethodSignature signature) { if (!PsiUtil.isAccessible( aClass.getProject(), hierarchicalMethodSignature.getMethod(), aClass, aClass)) return; HierarchicalMethodSignatureImpl existing = map.get(signature); if (existing == null) { HierarchicalMethodSignatureImpl copy = copy(hierarchicalMethodSignature); LOG.assertTrue(copy.getMethod().isValid()); map.put(signature, copy); } else if (isReturnTypeIsMoreSpecificThan(hierarchicalMethodSignature, existing) && isSuperMethod(aClass, hierarchicalMethodSignature, existing)) { HierarchicalMethodSignatureImpl newSuper = copy(hierarchicalMethodSignature); mergeSupers(newSuper, existing); LOG.assertTrue(newSuper.getMethod().isValid()); map.put(signature, newSuper); } else if (isSuperMethod(aClass, existing, hierarchicalMethodSignature)) { mergeSupers(existing, hierarchicalMethodSignature); } // just drop an invalid method declaration there - to highlight accordingly else if (!result.containsKey(signature)) { LOG.assertTrue(hierarchicalMethodSignature.getMethod().isValid()); result.put(signature, hierarchicalMethodSignature); } }
public static boolean inheritsITestListener(@NotNull PsiClass psiClass) { final Project project = psiClass.getProject(); final PsiClass aListenerClass = JavaPsiFacade.getInstance(project) .findClass(ITestNGListener.class.getName(), GlobalSearchScope.allScope(project)); return aListenerClass != null && psiClass.isInheritor(aListenerClass, true); }
private static PsiType createType(PsiClass cls, PsiSubstitutor currentSubstitutor, int arrayDim) { final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(cls.getProject()).getElementFactory(); PsiType newType = elementFactory.createType(cls, currentSubstitutor); for (int i = 0; i < arrayDim; i++) { newType = newType.createArrayType(); } return newType; }
public GrPullUpHelper( PsiClass aClass, PsiClass superClass, GrMemberInfo[] infos, DocCommentPolicy policy) { super(aClass.getProject()); mySourceClass = aClass; myTargetSuperClass = (GrTypeDefinition) superClass; myMembersToMove = infos; myDocCommentPolicy = policy; }
public ExtractClassProcessor( PsiClass sourceClass, List<PsiField> fields, List<PsiMethod> methods, List<PsiClass> classes, String packageName, MoveDestination moveDestination, String newClassName, String newVisibility, boolean generateAccessors, List<MemberInfo> enumConstants) { super(sourceClass.getProject()); this.sourceClass = sourceClass; this.newPackageName = packageName; myMoveDestination = moveDestination; myNewVisibility = newVisibility; myGenerateAccessors = generateAccessors; this.enumConstants = new ArrayList<PsiField>(); for (MemberInfo constant : enumConstants) { if (constant.isChecked()) { this.enumConstants.add((PsiField) constant.getMember()); } } this.fields = new ArrayList<PsiField>(fields); this.methods = new ArrayList<PsiMethod>(methods); this.innerClasses = new ArrayList<PsiClass>(classes); this.newClassName = newClassName; delegateFieldName = calculateDelegateFieldName(); requiresBackpointer = new BackpointerUsageVisitor(fields, innerClasses, methods, sourceClass) .backpointerRequired(); if (requiresBackpointer) { ContainerUtil.addAll(typeParams, sourceClass.getTypeParameters()); } else { final Set<PsiTypeParameter> typeParamSet = new HashSet<PsiTypeParameter>(); final TypeParametersVisitor visitor = new TypeParametersVisitor(typeParamSet); for (PsiField field : fields) { field.accept(visitor); } for (PsiMethod method : methods) { method.accept(visitor); // do not include method's type parameters in class signature typeParamSet.removeAll(Arrays.asList(method.getTypeParameters())); } typeParams.addAll(typeParamSet); } myClass = new WriteCommandAction<PsiClass>(myProject, getCommandName()) { @Override protected void run(@NotNull Result<PsiClass> result) throws Throwable { result.setResult(buildClass()); } }.execute().getResultObject(); myExtractEnumProcessor = new ExtractEnumProcessor(myProject, this.enumConstants, myClass); }
@NotNull public static PsiClassType[] getExtendsListTypes(@NotNull PsiClass psiClass) { if (psiClass.isEnum()) { PsiClassType enumSuperType = getEnumSuperType( psiClass, JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory()); return enumSuperType == null ? PsiClassType.EMPTY_ARRAY : new PsiClassType[] {enumSuperType}; } if (psiClass.isAnnotationType()) { return new PsiClassType[] { getAnnotationSuperType( psiClass, JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory()) }; } final PsiReferenceList extendsList = psiClass.getExtendsList(); if (extendsList != null) { return extendsList.getReferencedTypes(); } return PsiClassType.EMPTY_ARRAY; }
public PullUpProcessor( PsiClass sourceClass, PsiClass targetSuperClass, MemberInfo[] membersToMove, DocCommentPolicy javaDocPolicy) { super(sourceClass.getProject()); mySourceClass = sourceClass; myTargetSuperClass = targetSuperClass; myMembersToMove = membersToMove; myJavaDocPolicy = javaDocPolicy; }
private static void generateDelegate(JavaChangeInfo changeInfo) throws IncorrectOperationException { final PsiMethod delegate = (PsiMethod) changeInfo.getMethod().copy(); final PsiClass targetClass = changeInfo.getMethod().getContainingClass(); LOG.assertTrue(!targetClass.isInterface()); PsiElementFactory factory = JavaPsiFacade.getElementFactory(targetClass.getProject()); ChangeSignatureProcessor.makeEmptyBody(factory, delegate); final PsiCallExpression callExpression = ChangeSignatureProcessor.addDelegatingCallTemplate(delegate, changeInfo.getNewName()); addDelegateArguments(changeInfo, factory, callExpression); targetClass.addBefore(delegate, changeInfo.getMethod()); }
@Override protected boolean preprocessUsages(@NotNull final Ref<UsageInfo[]> refUsages) { final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>(); myExtractEnumProcessor.findEnumConstantConflicts(refUsages); if (!DestinationFolderComboBox.isAccessible( myProject, sourceClass.getContainingFile().getVirtualFile(), myClass.getContainingFile().getContainingDirectory().getVirtualFile())) { conflicts.putValue( sourceClass, "Extracted class won't be accessible in " + RefactoringUIUtil.getDescription(sourceClass, true)); } ApplicationManager.getApplication() .runWriteAction( new Runnable() { public void run() { myClass.delete(); } }); final Project project = sourceClass.getProject(); final GlobalSearchScope scope = GlobalSearchScope.allScope(project); final PsiClass existingClass = JavaPsiFacade.getInstance(project).findClass(getQualifiedName(), scope); if (existingClass != null) { conflicts.putValue( existingClass, RefactorJBundle.message("cannot.perform.the.refactoring") + RefactorJBundle.message("there.already.exists.a.class.with.the.chosen.name")); } if (!myGenerateAccessors) { calculateInitializersConflicts(conflicts); final NecessaryAccessorsVisitor visitor = checkNecessaryGettersSetters4ExtractedClass(); final NecessaryAccessorsVisitor srcVisitor = checkNecessaryGettersSetters4SourceClass(); final Set<PsiField> fieldsNeedingGetter = new LinkedHashSet<PsiField>(); fieldsNeedingGetter.addAll(visitor.getFieldsNeedingGetter()); fieldsNeedingGetter.addAll(srcVisitor.getFieldsNeedingGetter()); for (PsiField field : fieldsNeedingGetter) { conflicts.putValue(field, "Field \'" + field.getName() + "\' needs getter"); } final Set<PsiField> fieldsNeedingSetter = new LinkedHashSet<PsiField>(); fieldsNeedingSetter.addAll(visitor.getFieldsNeedingSetter()); fieldsNeedingSetter.addAll(srcVisitor.getFieldsNeedingSetter()); for (PsiField field : fieldsNeedingSetter) { conflicts.putValue(field, "Field \'" + field.getName() + "\' needs setter"); } } checkConflicts(refUsages, conflicts); return showConflicts(conflicts, refUsages.get()); }
public static boolean nameCanBeImported(@NotNull String fqName, @NotNull PsiElement context) { final PsiClass containingClass = PsiTreeUtil.getParentOfType(context, PsiClass.class); if (containingClass != null) { if (fqName.equals(containingClass.getQualifiedName())) { return true; } final String shortName = ClassUtil.extractClassName(fqName); final PsiClass[] innerClasses = containingClass.getAllInnerClasses(); for (PsiClass innerClass : innerClasses) { if (innerClass.hasModifierProperty(PsiModifier.PRIVATE)) { continue; } if (innerClass.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) { if (!ClassUtils.inSamePackage(innerClass, containingClass)) { continue; } } final String className = innerClass.getName(); if (shortName.equals(className)) { return false; } } PsiField field = containingClass.findFieldByName(shortName, false); if (field != null) { return false; } field = containingClass.findFieldByName(shortName, true); if (field != null && PsiUtil.isAccessible(containingClass.getProject(), field, containingClass, null)) { return false; } } final PsiJavaFile file = PsiTreeUtil.getParentOfType(context, PsiJavaFile.class); if (file == null) { return false; } if (hasExactImportConflict(fqName, file)) { return false; } if (hasOnDemandImportConflict(fqName, file, true)) { return false; } if (containsConflictingReference(file, fqName)) { return false; } if (containsConflictingClass(fqName, file)) { return false; } return !containsConflictingClassName(fqName, file); }
@NotNull private static ParameterizedCachedValue<MembersMap, PsiClass> getValues( @NotNull PsiClass aClass) { ParameterizedCachedValue<MembersMap, PsiClass> value = aClass.getUserData(MAP_IN_CLASS_KEY); if (value == null) { value = CachedValuesManager.getManager(aClass.getProject()) .createParameterizedCachedValue(ByNameCachedValueProvider.INSTANCE, false); // Do not cache for nonphysical elements if (aClass.isPhysical()) { value = ((UserDataHolderEx) aClass).putUserDataIfAbsent(MAP_IN_CLASS_KEY, value); } } return value; }
@Nullable public static PsiMethod findPsiMethod(PsiManager manager, String externalName) { final int spaceIdx = externalName.indexOf(' '); final String className = externalName.substring(0, spaceIdx); final PsiClass psiClass = ClassUtil.findPsiClass(manager, className); if (psiClass == null) return null; try { PsiElementFactory factory = JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory(); String methodSignature = externalName.substring(spaceIdx + 1); PsiMethod patternMethod = factory.createMethodFromText(methodSignature, psiClass); return psiClass.findMethodBySignature(patternMethod, false); } catch (IncorrectOperationException e) { // Do nothing. Returning null is acceptable in this case. return null; } }
private List<PsiClass> calculateInterfacesSupported() { final List<PsiClass> out = new ArrayList<PsiClass>(); final PsiClass[] supers = sourceClass.getSupers(); for (PsiClass superClass : supers) { if (!superClass.isInterface()) { continue; } final PsiMethod[] superclassMethods = superClass.getMethods(); if (superclassMethods.length == 0) { continue; } boolean allMethodsCovered = true; for (PsiMethod method : superclassMethods) { boolean isCovered = false; for (PsiMethod movedMethod : methods) { if (isSuperMethod(method, movedMethod)) { isCovered = true; break; } } if (!isCovered) { allMethodsCovered = false; break; } } if (allMethodsCovered) { out.add(superClass); } } final Project project = sourceClass.getProject(); final PsiManager manager = sourceClass.getManager(); final GlobalSearchScope scope = GlobalSearchScope.allScope(project); if (usesDefaultSerialization(sourceClass)) { final PsiClass serializable = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.io.Serializable", scope); out.add(serializable); } if (usesDefaultClone(sourceClass)) { final PsiClass cloneable = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Cloneable", scope); out.add(cloneable); } return out; }
private static boolean usesDefaultClone(PsiClass aClass) { final Project project = aClass.getProject(); final PsiManager manager = aClass.getManager(); final GlobalSearchScope scope = GlobalSearchScope.allScope(project); final PsiClass cloneable = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Cloneable", scope); if (!InheritanceUtil.isInheritorOrSelf(aClass, cloneable, true)) { return false; } final PsiMethod[] methods = aClass.findMethodsByName("clone", false); for (PsiMethod method : methods) { final PsiParameterList parameterList = method.getParameterList(); final PsiParameter[] parameters = parameterList.getParameters(); if (parameters.length == 0) { return false; } } return true; }
public static boolean isSourceLevelAccessible( PsiElement context, PsiClass psiClass, final boolean pkgContext) { if (!JavaPsiFacade.getInstance(psiClass.getProject()) .getResolveHelper() .isAccessible(psiClass, context, null)) { return false; } if (pkgContext) { PsiClass topLevel = PsiUtil.getTopLevelClass(psiClass); if (topLevel != null) { String fqName = topLevel.getQualifiedName(); if (fqName != null && StringUtil.isEmpty(StringUtil.getPackageName(fqName))) { return false; } } } return true; }
private static boolean isSuperMethod( PsiClass aClass, HierarchicalMethodSignature hierarchicalMethodSignature, HierarchicalMethodSignature superSignatureHierarchical) { PsiMethod superMethod = superSignatureHierarchical.getMethod(); PsiClass superClass = superMethod.getContainingClass(); PsiClass containingClass = hierarchicalMethodSignature.getMethod().getContainingClass(); if (!superMethod.isConstructor()) { if (!aClass.equals(superClass)) { if (PsiUtil.isAccessible(aClass.getProject(), superMethod, aClass, aClass)) { if (MethodSignatureUtil.isSubsignature( superSignatureHierarchical, hierarchicalMethodSignature)) { if (superClass != null) { if (superClass.isInterface() || CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) { if (superMethod.hasModifierProperty(PsiModifier.DEFAULT) || hierarchicalMethodSignature .getMethod() .hasModifierProperty(PsiModifier.DEFAULT)) { return !InheritanceUtil.isInheritorOrSelf(superClass, containingClass, true); } return true; } if (containingClass != null) { if (containingClass.isInterface()) { return false; } if (!aClass.isInterface() && !InheritanceUtil.isInheritorOrSelf(superClass, containingClass, true)) { return true; } } } } } } } return false; }
@Override public PsiType visitClassType(PsiClassType classType) { final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics(); final PsiClass aClass = resolveResult.getElement(); if (aClass == null) return classType; if (aClass instanceof PsiTypeParameter) { final PsiTypeParameter typeParameter = (PsiTypeParameter) aClass; if (containsInMap(typeParameter)) { return substituteTypeParameter(typeParameter); } else { return classType; } } final Map<PsiTypeParameter, PsiType> hashMap = new HashMap<PsiTypeParameter, PsiType>(2); if (!processClass(aClass, resolveResult.getSubstitutor(), hashMap)) { return null; } return JavaPsiFacade.getInstance(aClass.getProject()) .getElementFactory() .createType(aClass, createSubstitutor(hashMap), classType.getLanguageLevel()); }
@NotNull public static SearchScope getClassUseScope(@NotNull PsiClass aClass) { if (aClass instanceof PsiAnonymousClass) { return new LocalSearchScope(aClass); } final GlobalSearchScope maximalUseScope = ResolveScopeManager.getElementUseScope(aClass); PsiFile file = aClass.getContainingFile(); if (PsiImplUtil.isInServerPage(file)) return maximalUseScope; final PsiClass containingClass = aClass.getContainingClass(); if (aClass.hasModifierProperty(PsiModifier.PUBLIC) || aClass.hasModifierProperty(PsiModifier.PROTECTED)) { return containingClass == null ? maximalUseScope : containingClass.getUseScope(); } else if (aClass.hasModifierProperty(PsiModifier.PRIVATE) || aClass instanceof PsiTypeParameter) { PsiClass topClass = PsiUtil.getTopLevelClass(aClass); return new LocalSearchScope(topClass == null ? aClass.getContainingFile() : topClass); } else { PsiPackage aPackage = null; if (file instanceof PsiJavaFile) { aPackage = JavaPsiFacade.getInstance(aClass.getProject()) .findPackage(((PsiJavaFile) file).getPackageName()); } if (aPackage == null) { PsiDirectory dir = file.getContainingDirectory(); if (dir != null) { aPackage = JavaDirectoryService.getInstance().getPackage(dir); } } if (aPackage != null) { SearchScope scope = PackageScope.packageScope(aPackage, false); scope = scope.intersectWith(maximalUseScope); return scope; } return new LocalSearchScope(file); } }
private String calculateDelegateFieldName() { final Project project = sourceClass.getProject(); final CodeStyleSettingsManager settingsManager = CodeStyleSettingsManager.getInstance(project); final CodeStyleSettings settings = settingsManager.getCurrentSettings(); final String baseName = settings.FIELD_NAME_PREFIX.length() == 0 ? StringUtil.decapitalize(newClassName) : newClassName; String name = settings.FIELD_NAME_PREFIX + baseName + settings.FIELD_NAME_SUFFIX; if (!existsFieldWithName(name) && !PsiNameHelper.getInstance(project).isKeyword(name)) { return name; } int counter = 1; while (true) { name = settings.FIELD_NAME_PREFIX + baseName + counter + settings.FIELD_NAME_SUFFIX; if (!existsFieldWithName(name) && !PsiNameHelper.getInstance(project).isKeyword(name)) { return name; } counter++; } }
private static boolean usesDefaultSerialization(PsiClass aClass) { final Project project = aClass.getProject(); final PsiManager manager = aClass.getManager(); final GlobalSearchScope scope = GlobalSearchScope.allScope(project); final PsiClass serializable = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.io.Serializable", scope); if (!InheritanceUtil.isInheritorOrSelf(aClass, serializable, true)) { return false; } final PsiMethod[] methods = aClass.findMethodsByName("writeObject", false); for (PsiMethod method : methods) { final PsiParameterList parameterList = method.getParameterList(); final PsiParameter[] parameters = parameterList.getParameters(); if (parameters.length == 1) { final PsiType type = parameters[0].getType(); final String text = type.getCanonicalText(); if ("java.io.DataOutputStream".equals(text)) { return false; } } } return true; }
private void makeArray(PsiVariable variable) throws IncorrectOperationException { PsiType type = variable.getType(); PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory(); PsiType newType = type.createArrayType(); PsiDeclarationStatement variableDeclarationStatement; PsiExpression initializer = variable.getInitializer(); if (initializer == null) { String expression = "[1]"; while (type instanceof PsiArrayType) { expression += "[1]"; type = ((PsiArrayType) type).getComponentType(); } PsiExpression init = factory.createExpressionFromText("new " + type.getCanonicalText() + expression, variable); variableDeclarationStatement = factory.createVariableDeclarationStatement(variable.getName(), newType, init); } else { PsiExpression init = factory.createExpressionFromText("{ " + initializer.getText() + " }", variable); variableDeclarationStatement = factory.createVariableDeclarationStatement(variable.getName(), newType, init); } PsiVariable newVariable = (PsiVariable) variableDeclarationStatement.getDeclaredElements()[0]; PsiUtil.setModifierProperty(newVariable, PsiModifier.FINAL, true); PsiElement newExpression = factory.createExpressionFromText(variable.getName() + "[0]", variable); PsiElement outerCodeBlock = PsiUtil.getVariableCodeBlock(variable, null); if (outerCodeBlock == null) return; List<PsiReferenceExpression> outerReferences = new ArrayList<PsiReferenceExpression>(); collectReferences(outerCodeBlock, variable, outerReferences); replaceReferences(outerReferences, newExpression); variable.replace(newVariable); }
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; }
private static boolean processDeclarationsInClassNotCached( @NotNull PsiClass aClass, @NotNull PsiScopeProcessor processor, @NotNull ResolveState state, @Nullable Set<PsiClass> visited, PsiElement last, @NotNull PsiElement place, boolean isRaw, @NotNull LanguageLevel languageLevel) { if (visited == null) visited = new THashSet<PsiClass>(); if (!visited.add(aClass)) return true; processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass); final ElementClassHint classHint = processor.getHint(ElementClassHint.KEY); final NameHint nameHint = processor.getHint(NameHint.KEY); if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.FIELD)) { if (nameHint != null) { final PsiField fieldByName = aClass.findFieldByName(nameHint.getName(state), false); if (fieldByName != null && !processor.execute(fieldByName, state)) return false; } else { final PsiField[] fields = aClass.getFields(); for (final PsiField field : fields) { if (!processor.execute(field, state)) return false; } } } PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory(); if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) { PsiSubstitutor baseSubstitutor = state.get(PsiSubstitutor.KEY); final PsiMethod[] methods = nameHint != null ? aClass.findMethodsByName(nameHint.getName(state), false) : aClass.getMethods(); for (final PsiMethod method : methods) { PsiSubstitutor finalSubstitutor = checkRaw(isRaw, factory, method, baseSubstitutor); ResolveState methodState = finalSubstitutor == baseSubstitutor ? state : state.put(PsiSubstitutor.KEY, finalSubstitutor); if (!processor.execute(method, methodState)) return false; } } if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) { if (last != null && last.getParent() == aClass) { // Parameters final PsiTypeParameterList list = aClass.getTypeParameterList(); if (list != null && !list.processDeclarations(processor, ResolveState.initial(), last, place)) return false; } if (!(last instanceof PsiReferenceList) && !(last instanceof PsiModifierList)) { // Inners if (nameHint != null) { final PsiClass inner = aClass.findInnerClassByName(nameHint.getName(state), false); if (inner != null) { if (!processor.execute(inner, state)) return false; } } else { final PsiClass[] inners = aClass.getInnerClasses(); for (final PsiClass inner : inners) { if (!processor.execute(inner, state)) return false; } } } } return last instanceof PsiReferenceList || processSuperTypes( aClass, processor, visited, last, place, state, isRaw, factory, languageLevel); }
private static AllowedValues parseBeanInfo(@NotNull PsiModifierListOwner owner) { PsiMethod method = null; if (owner instanceof PsiParameter) { PsiParameter parameter = (PsiParameter) owner; PsiElement scope = parameter.getDeclarationScope(); if (!(scope instanceof PsiMethod)) return null; PsiElement nav = scope.getNavigationElement(); if (!(nav instanceof PsiMethod)) return null; method = (PsiMethod) nav; if (method.isConstructor()) { // not a property, try the @ConstructorProperties({"prop"}) PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, "java.beans.ConstructorProperties"); if (annotation == null) return null; PsiAnnotationMemberValue value = annotation.findAttributeValue("value"); if (!(value instanceof PsiArrayInitializerMemberValue)) return null; PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue) value).getInitializers(); PsiElement parent = parameter.getParent(); if (!(parent instanceof PsiParameterList)) return null; int index = ((PsiParameterList) parent).getParameterIndex(parameter); if (index >= initializers.length) return null; PsiAnnotationMemberValue initializer = initializers[index]; if (!(initializer instanceof PsiLiteralExpression)) return null; Object val = ((PsiLiteralExpression) initializer).getValue(); if (!(val instanceof String)) return null; PsiMethod setter = PropertyUtil.findPropertySetter( method.getContainingClass(), (String) val, false, false); if (setter == null) return null; // try the @beaninfo of the corresponding setter method = (PsiMethod) setter.getNavigationElement(); } } else if (owner instanceof PsiMethod) { PsiElement nav = owner.getNavigationElement(); if (!(nav instanceof PsiMethod)) return null; method = (PsiMethod) nav; } if (method == null) return null; PsiClass aClass = method.getContainingClass(); if (aClass == null) return null; if (PropertyUtil.isSimplePropertyGetter(method)) { List<PsiMethod> setters = PropertyUtil.getSetters(aClass, PropertyUtil.getPropertyNameByGetter(method)); if (setters.size() != 1) return null; method = setters.get(0); } if (!PropertyUtil.isSimplePropertySetter(method)) return null; PsiDocComment doc = method.getDocComment(); if (doc == null) return null; PsiDocTag beaninfo = doc.findTagByName("beaninfo"); if (beaninfo == null) return null; String data = StringUtil.join( beaninfo.getDataElements(), new Function<PsiElement, String>() { @Override public String fun(PsiElement element) { return element.getText(); } }, "\n"); int enumIndex = StringUtil.indexOfSubstringEnd(data, "enum:"); if (enumIndex == -1) return null; data = data.substring(enumIndex); int colon = data.indexOf(":"); int last = colon == -1 ? data.length() : data.substring(0, colon).lastIndexOf("\n"); data = data.substring(0, last); List<PsiAnnotationMemberValue> values = new ArrayList<PsiAnnotationMemberValue>(); for (String line : StringUtil.splitByLines(data)) { List<String> words = StringUtil.split(line, " ", true, true); if (words.size() != 2) continue; String ref = words.get(1); PsiExpression constRef = JavaPsiFacade.getElementFactory(aClass.getProject()) .createExpressionFromText(ref, aClass); if (!(constRef instanceof PsiReferenceExpression)) continue; PsiReferenceExpression expr = (PsiReferenceExpression) constRef; values.add(expr); } if (values.isEmpty()) return null; PsiAnnotationMemberValue[] array = values.toArray(new PsiAnnotationMemberValue[values.size()]); return new AllowedValues(array, false); }
private static boolean processCachedMembersByName( @NotNull PsiClass aClass, @NotNull PsiScopeProcessor processor, @NotNull ResolveState state, @Nullable Set<PsiClass> visited, PsiElement last, @NotNull PsiElement place, boolean isRaw, @NotNull PsiSubstitutor substitutor, @NotNull MembersMap value, String name, @NotNull LanguageLevel languageLevel) { final ElementClassHint classHint = processor.getHint(ElementClassHint.KEY); PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory(); if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.FIELD)) { final PsiField fieldByName = aClass.findFieldByName(name, false); if (fieldByName != null) { processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass); if (!processor.execute(fieldByName, state)) return false; } else { final Map<String, List<Pair<PsiMember, PsiSubstitutor>>> allFieldsMap = value.get(MemberType.FIELD); final List<Pair<PsiMember, PsiSubstitutor>> list = allFieldsMap.get(name); if (list != null) { for (final Pair<PsiMember, PsiSubstitutor> candidate : list) { PsiMember candidateField = candidate.getFirst(); PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor( candidateField.getContainingClass(), candidate.getSecond(), aClass, substitutor, factory, languageLevel); processor.handleEvent( PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, candidateField.getContainingClass()); if (!processor.execute(candidateField, state.put(PsiSubstitutor.KEY, finalSubstitutor))) return false; } } } } if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) { if (last != null && last.getParent() == aClass) { if (last instanceof PsiClass) { if (!processor.execute(last, state)) return false; } // Parameters final PsiTypeParameterList list = aClass.getTypeParameterList(); if (list != null && !list.processDeclarations(processor, state, last, place)) return false; } if (!(last instanceof PsiReferenceList)) { final PsiClass classByName = aClass.findInnerClassByName(name, false); if (classByName != null) { processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass); if (!processor.execute(classByName, state)) return false; } else { Map<String, List<Pair<PsiMember, PsiSubstitutor>>> allClassesMap = value.get(MemberType.CLASS); List<Pair<PsiMember, PsiSubstitutor>> list = allClassesMap.get(name); if (list != null) { for (final Pair<PsiMember, PsiSubstitutor> candidate : list) { PsiMember inner = candidate.getFirst(); PsiClass containingClass = inner.getContainingClass(); if (containingClass != null) { PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor( containingClass, candidate.getSecond(), aClass, substitutor, factory, languageLevel); processor.handleEvent( PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, containingClass); if (!processor.execute(inner, state.put(PsiSubstitutor.KEY, finalSubstitutor))) return false; } } } } } } if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) { if (processor instanceof MethodResolverProcessor) { final MethodResolverProcessor methodResolverProcessor = (MethodResolverProcessor) processor; if (methodResolverProcessor.isConstructor()) { final PsiMethod[] constructors = aClass.getConstructors(); methodResolverProcessor.handleEvent( PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass); for (PsiMethod constructor : constructors) { if (!methodResolverProcessor.execute(constructor, state)) return false; } return true; } } Map<String, List<Pair<PsiMember, PsiSubstitutor>>> allMethodsMap = value.get(MemberType.METHOD); List<Pair<PsiMember, PsiSubstitutor>> list = allMethodsMap.get(name); if (list != null) { for (final Pair<PsiMember, PsiSubstitutor> candidate : list) { ProgressIndicatorProvider.checkCanceled(); PsiMethod candidateMethod = (PsiMethod) candidate.getFirst(); if (processor instanceof MethodResolverProcessor) { if (candidateMethod.isConstructor() != ((MethodResolverProcessor) processor).isConstructor()) continue; } final PsiClass containingClass = candidateMethod.getContainingClass(); if (visited != null && visited.contains(candidateMethod.getContainingClass())) { continue; } PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor( containingClass, candidate.getSecond(), aClass, substitutor, factory, languageLevel); finalSubstitutor = checkRaw(isRaw, factory, candidateMethod, finalSubstitutor); processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, containingClass); if (!processor.execute(candidateMethod, state.put(PsiSubstitutor.KEY, finalSubstitutor))) return false; } if (visited != null) { for (Pair<PsiMember, PsiSubstitutor> aList : list) { visited.add(aList.getFirst().getContainingClass()); } } } } return true; }
private PsiClass buildClass() { final PsiManager manager = sourceClass.getManager(); final Project project = sourceClass.getProject(); final ExtractedClassBuilder extractedClassBuilder = new ExtractedClassBuilder(); extractedClassBuilder.setProject(myProject); extractedClassBuilder.setClassName(newClassName); extractedClassBuilder.setPackageName(newPackageName); extractedClassBuilder.setOriginalClassName(sourceClass.getQualifiedName()); extractedClassBuilder.setRequiresBackPointer(requiresBackpointer); extractedClassBuilder.setExtractAsEnum(enumConstants); for (PsiField field : fields) { extractedClassBuilder.addField(field); } for (PsiMethod method : methods) { extractedClassBuilder.addMethod(method); } for (PsiClass innerClass : innerClasses) { extractedClassBuilder.addInnerClass( innerClass, innerClassesToMakePublic.contains(innerClass)); } extractedClassBuilder.setTypeArguments(typeParams); final List<PsiClass> interfaces = calculateInterfacesSupported(); extractedClassBuilder.setInterfaces(interfaces); if (myGenerateAccessors) { final NecessaryAccessorsVisitor visitor = checkNecessaryGettersSetters4ExtractedClass(); sourceClass.accept(visitor); extractedClassBuilder.setFieldsNeedingGetters(visitor.getFieldsNeedingGetter()); extractedClassBuilder.setFieldsNeedingSetters(visitor.getFieldsNeedingSetter()); } final String classString = extractedClassBuilder.buildBeanClass(); if (extractInnerClass) { final PsiFileFactory factory = PsiFileFactory.getInstance(project); final PsiJavaFile newFile = (PsiJavaFile) factory.createFileFromText( newClassName + ".java", JavaFileType.INSTANCE, classString); final PsiClass psiClass = newFile.getClasses()[0]; if (!psiClass.isEnum()) { final PsiModifierList modifierList = psiClass.getModifierList(); assert modifierList != null; modifierList.setModifierProperty(PsiModifier.STATIC, true); } final PsiElement addedClass = sourceClass.add(psiClass); return (PsiClass) CodeStyleManager.getInstance(manager) .reformat( JavaCodeStyleManager.getInstance(project).shortenClassReferences(addedClass)); } try { final PsiFile containingFile = sourceClass.getContainingFile(); final PsiDirectory directory; final PsiDirectory containingDirectory = containingFile.getContainingDirectory(); if (myMoveDestination != null) { directory = myMoveDestination.getTargetDirectory(containingDirectory); } else { final Module module = ModuleUtil.findModuleForPsiElement(containingFile); assert module != null; directory = PackageUtil.findOrCreateDirectoryForPackage( module, newPackageName, containingDirectory, false, true); } if (directory != null) { final PsiFileFactory factory = PsiFileFactory.getInstance(project); final PsiFile newFile = factory.createFileFromText(newClassName + ".java", JavaFileType.INSTANCE, classString); final PsiElement addedFile = directory.add(newFile); final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject()); final PsiElement shortenedFile = JavaCodeStyleManager.getInstance(project).shortenClassReferences(addedFile); return ((PsiJavaFile) codeStyleManager.reformat(shortenedFile)).getClasses()[0]; } else { return null; } } catch (IncorrectOperationException e) { return null; } }
private static Map<MethodSignature, HierarchicalMethodSignature> buildMethodHierarchy( PsiClass aClass, PsiSubstitutor substitutor, final boolean includePrivates, final Set<PsiClass> visited, boolean isInRawContext) { Map<MethodSignature, HierarchicalMethodSignature> result = new LinkedHashMap<MethodSignature, HierarchicalMethodSignature>(); final Map<MethodSignature, List<PsiMethod>> sameParameterErasureMethods = new THashMap<MethodSignature, List<PsiMethod>>( MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY); Map<MethodSignature, HierarchicalMethodSignatureImpl> map = new THashMap<MethodSignature, HierarchicalMethodSignatureImpl>( new TObjectHashingStrategy<MethodSignature>() { @Override public int computeHashCode(MethodSignature signature) { return MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY.computeHashCode( signature); } @Override public boolean equals(MethodSignature o1, MethodSignature o2) { if (!MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY.equals(o1, o2)) return false; List<PsiMethod> list = sameParameterErasureMethods.get(o1); boolean toCheckReturnType = list != null && list.size() > 1; if (!toCheckReturnType) return true; PsiType returnType1 = ((MethodSignatureBackedByPsiMethod) o1).getMethod().getReturnType(); PsiType returnType2 = ((MethodSignatureBackedByPsiMethod) o2).getMethod().getReturnType(); if (returnType1 == null && returnType2 == null) return true; if (returnType1 == null || returnType2 == null) return false; PsiType erasure1 = TypeConversionUtil.erasure(o1.getSubstitutor().substitute(returnType1)); PsiType erasure2 = TypeConversionUtil.erasure(o2.getSubstitutor().substitute(returnType2)); return erasure1.equals(erasure2); } }); for (PsiMethod method : aClass.getMethods()) { if (!method.isValid()) { throw new PsiInvalidElementAccessException( method, "class.valid=" + aClass.isValid() + "; name=" + method.getName()); } if (!includePrivates && method.hasModifierProperty(PsiModifier.PRIVATE)) continue; final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, substitutor, isInRawContext); HierarchicalMethodSignatureImpl newH = new HierarchicalMethodSignatureImpl(signature); List<PsiMethod> list = sameParameterErasureMethods.get(signature); if (list == null) { list = new SmartList<PsiMethod>(); sameParameterErasureMethods.put(signature, list); } list.add(method); LOG.assertTrue(newH.getMethod().isValid()); result.put(signature, newH); map.put(signature, newH); } for (PsiClassType superType : aClass.getSuperTypes()) { PsiClassType.ClassResolveResult superTypeResolveResult = superType.resolveGenerics(); PsiClass superClass = superTypeResolveResult.getElement(); if (superClass == null) continue; if (!visited.add(superClass)) continue; // cyclic inheritance final PsiSubstitutor superSubstitutor = superTypeResolveResult.getSubstitutor(); PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(superClass, superSubstitutor, substitutor, isInRawContext); final boolean isInRawContextSuper = (isInRawContext || PsiUtil.isRawSubstitutor(superClass, superSubstitutor)) && superClass.getTypeParameters().length != 0; Map<MethodSignature, HierarchicalMethodSignature> superResult = buildMethodHierarchy(superClass, finalSubstitutor, false, visited, isInRawContextSuper); visited.remove(superClass); List<Pair<MethodSignature, HierarchicalMethodSignature>> flattened = new ArrayList<Pair<MethodSignature, HierarchicalMethodSignature>>(); for (Map.Entry<MethodSignature, HierarchicalMethodSignature> entry : superResult.entrySet()) { HierarchicalMethodSignature hms = entry.getValue(); MethodSignature signature = entry.getKey(); PsiClass containingClass = hms.getMethod().getContainingClass(); List<HierarchicalMethodSignature> supers = new ArrayList<HierarchicalMethodSignature>(hms.getSuperSignatures()); for (HierarchicalMethodSignature aSuper : supers) { PsiClass superContainingClass = aSuper.getMethod().getContainingClass(); if (containingClass != null && superContainingClass != null && !containingClass.isInheritor(superContainingClass, true)) { // methods must be inherited from unrelated classes, so flatten hierarchy here // class C implements SAM1, SAM2 { void methodimpl() {} } // hms.getSuperSignatures().remove(aSuper); flattened.add( new Pair<MethodSignature, HierarchicalMethodSignature>(signature, aSuper)); } } putInMap(aClass, result, map, hms, signature); } for (Pair<MethodSignature, HierarchicalMethodSignature> pair : flattened) { putInMap(aClass, result, map, pair.second, pair.first); } } for (Map.Entry<MethodSignature, HierarchicalMethodSignatureImpl> entry : map.entrySet()) { HierarchicalMethodSignatureImpl hierarchicalMethodSignature = entry.getValue(); MethodSignature methodSignature = entry.getKey(); if (result.get(methodSignature) == null && PsiUtil.isAccessible( aClass.getProject(), hierarchicalMethodSignature.getMethod(), aClass, aClass)) { LOG.assertTrue(hierarchicalMethodSignature.getMethod().isValid()); result.put(methodSignature, hierarchicalMethodSignature); } } return result; }