@Nullable @Override protected RefactoringEventData getAfterData(UsageInfo[] usages) { RefactoringEventData data = new RefactoringEventData(); List<PsiElement> elements = new ArrayList<PsiElement>(); if (myNameToGetter != null) { elements.addAll(myNameToGetter.values()); } if (myNameToSetter != null) { elements.addAll(myNameToSetter.values()); } data.addElements(elements); return data; }
@Nullable private PsiMethod collectExceptions(List<PsiClassType> unhandled) { PsiElement targetElement = null; PsiMethod targetMethod = null; final PsiElement psiElement = myWrongElement instanceof PsiMethodReferenceExpression ? myWrongElement : PsiTreeUtil.getParentOfType( myWrongElement, PsiFunctionalExpression.class, PsiMethod.class); if (psiElement instanceof PsiFunctionalExpression) { targetMethod = LambdaUtil.getFunctionalInterfaceMethod(psiElement); targetElement = psiElement instanceof PsiLambdaExpression ? ((PsiLambdaExpression) psiElement).getBody() : psiElement; } else if (psiElement instanceof PsiMethod) { targetMethod = (PsiMethod) psiElement; targetElement = psiElement; } if (targetElement == null || targetMethod == null || !targetMethod.getThrowsList().isPhysical()) return null; List<PsiClassType> exceptions = getUnhandledExceptions(myWrongElement, targetElement, targetMethod); if (exceptions == null || exceptions.isEmpty()) return null; unhandled.addAll(exceptions); return targetMethod; }
private ClassMapCachingNulls<MultiHostInjector> getInjectorMap() { ClassMapCachingNulls<MultiHostInjector> cached = cachedInjectors; if (cached != null) { return cached; } Map<Class, MultiHostInjector[]> injectors = ContainerUtil.newHashMap(); List<MultiHostInjector> allInjectors = ContainerUtil.newArrayList(); allInjectors.addAll(myManualInjectors); Collections.addAll( allInjectors, MultiHostInjector.MULTIHOST_INJECTOR_EP_NAME.getExtensions(myProject)); if (LanguageInjector.EXTENSION_POINT_NAME.getExtensions().length > 0) { allInjectors.add(PsiManagerRegisteredInjectorsAdapter.INSTANCE); } for (MultiHostInjector injector : allInjectors) { for (Class<? extends PsiElement> place : injector.elementsToInjectIn()) { LOG.assertTrue(place != null, injector); MultiHostInjector[] existing = injectors.get(place); injectors.put( place, existing == null ? new MultiHostInjector[] {injector} : ArrayUtil.append(existing, injector)); } } ClassMapCachingNulls<MultiHostInjector> result = new ClassMapCachingNulls<>(injectors, new MultiHostInjector[0], allInjectors); cachedInjectors = result; return result; }
private static void getImplementListsInner( GrTypeDefinition grType, List<PsiClassType> result, Set<PsiClass> visited) { if (!visited.add(grType)) return; final PsiClassType[] implementsTypes = getReferenceListTypes(grType.getImplementsClause()); List<PsiClassType> fromDelegates = getImplementsFromDelegate(grType, visited); if (fromDelegates != null) { result.addAll(fromDelegates); } result.addAll(Arrays.asList(implementsTypes)); if (!grType.isInterface() && !ContainerUtil.or(implementsTypes, IS_GROOVY_OBJECT) && !ContainerUtil.or(getReferenceListTypes(grType.getExtendsClause()), IS_GROOVY_OBJECT)) { result.add(getGroovyObjectType(grType)); } }
public static void addExpandingReflectedMethods(List<PsiMethod> result, PsiMethod method) { if (method instanceof GrMethod) { final GrReflectedMethod[] reflectedMethods = ((GrMethod) method).getReflectedMethods(); if (reflectedMethods.length > 0) { result.addAll(Arrays.asList(reflectedMethods)); return; } } result.add(method); }
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); }
@Override public List<RefEntity> getChildren() { List<RefEntity> superChildren = super.getChildren(); if (myParameters == null) return superChildren; if (superChildren == null || superChildren.isEmpty()) return Arrays.<RefEntity>asList(myParameters); List<RefEntity> allChildren = new ArrayList<RefEntity>(superChildren.size() + myParameters.length); allChildren.addAll(superChildren); Collections.addAll(allChildren, myParameters); return allChildren; }
/** * The key method of contributor. It collects all delegating methods of clazz * * @param clazz class to process * @param processedWithoutDeprecated already visited classes which deprecated methods were not * processsed * @param processedAll already visited classes which all methods were processed * @param collector result collection */ private static void process( PsiClass clazz, PsiSubstitutor superClassSubstitutor, boolean shouldProcessDeprecated, Set<PsiClass> processedWithoutDeprecated, Set<PsiClass> processedAll, List<PsiMethod> collector, GrTypeDefinition classToDelegateTo, boolean keepParameterAnnotations) { final List<PsiMethod> result = new ArrayList<PsiMethod>(); // process super methods before delegated methods for (PsiClassType superType : getSuperTypes(clazz)) { processClassInner( superType, superClassSubstitutor, shouldProcessDeprecated, result, classToDelegateTo, processedWithoutDeprecated, processedAll, keepParameterAnnotations); } if (clazz instanceof GrTypeDefinition) { // search for @Delegate fields and collect methods from them for (GrField field : ((GrTypeDefinition) clazz).getFields()) { final PsiAnnotation delegate = PsiImplUtil.getAnnotation(field, GroovyCommonClassNames.GROOVY_LANG_DELEGATE); if (delegate == null) continue; final PsiType type = field.getDeclaredType(); if (!(type instanceof PsiClassType)) continue; processClassInner( (PsiClassType) type, superClassSubstitutor, shouldDelegateDeprecated(delegate), result, classToDelegateTo, processedWithoutDeprecated, processedAll, shouldKeepParameterAnnotations(delegate)); } } collector.addAll(result); }
@NotNull @Override public RefElement[] getEntryPoints() { validateEntryPoints(); List<RefElement> entries = new ArrayList<RefElement>(); Collection<SmartRefElementPointer> collection = myPersistentEntryPoints.values(); for (SmartRefElementPointer refElementPointer : collection) { final RefEntity elt = refElementPointer.getRefElement(); if (elt instanceof RefElement) { entries.add((RefElement) elt); } } entries.addAll(myTemporaryEntryPoints); return entries.toArray(new RefElement[entries.size()]); }
public void findUsages(@NotNull List<FixableUsageInfo> usages) { for (PsiField field : fields) { findUsagesForField(field, usages); usages.add(new RemoveField(field)); } usages.addAll( myExtractEnumProcessor.findEnumConstantUsages(new ArrayList<FixableUsageInfo>(usages))); for (PsiClass innerClass : innerClasses) { findUsagesForInnerClass(innerClass, usages); usages.add(new RemoveInnerClass(innerClass)); } for (PsiMethod method : methods) { if (method.hasModifierProperty(PsiModifier.STATIC)) { findUsagesForStaticMethod(method, usages); } else { findUsagesForMethod(method, usages); } } }
@Override protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) { if (!Registry.is("editor.injected.highlighting.enabled")) return; final Set<HighlightInfo> gotHighlights = new THashSet<HighlightInfo>(100); final List<PsiElement> inside = new ArrayList<PsiElement>(); final List<PsiElement> outside = new ArrayList<PsiElement>(); List<ProperTextRange> insideRanges = new ArrayList<ProperTextRange>(); List<ProperTextRange> outsideRanges = new ArrayList<ProperTextRange>(); // TODO: this thing is just called TWICE with same arguments eating CPU on huge files :( Divider.divideInsideAndOutside( myFile, myRestrictRange.getStartOffset(), myRestrictRange.getEndOffset(), myPriorityRange, inside, insideRanges, outside, outsideRanges, false, SHOULD_HIGHIGHT_FILTER); // all infos for the "injected fragment for the host which is inside" are indeed inside // but some of the infos for the "injected fragment for the host which is outside" can be still // inside Set<HighlightInfo> injectedResult = new THashSet<HighlightInfo>(); Set<PsiFile> injected = getInjectedPsiFiles(inside, outside, progress); setProgressLimit(injected.size()); if (!addInjectedPsiHighlights( injected, progress, Collections.synchronizedSet(injectedResult))) { throw new ProcessCanceledException(); } final List<HighlightInfo> injectionsOutside = new ArrayList<HighlightInfo>(gotHighlights.size()); Set<HighlightInfo> result; synchronized (injectedResult) { // sync here because all writes happened in another thread result = injectedResult; } for (HighlightInfo info : result) { if (myRestrictRange.contains(info)) { gotHighlights.add(info); } else { // nonconditionally apply injected results regardless whether they are in // myStartOffset,myEndOffset injectionsOutside.add(info); } } if (!injectionsOutside.isEmpty()) { final ProperTextRange priorityIntersection = myPriorityRange.intersection(myRestrictRange); if ((!inside.isEmpty() || !gotHighlights.isEmpty()) && priorityIntersection != null) { // do not apply when there were no elements to highlight // clear infos found in visible area to avoid applying them twice final List<HighlightInfo> toApplyInside = new ArrayList<HighlightInfo>(gotHighlights); myHighlights.addAll(toApplyInside); gotHighlights.clear(); myHighlightInfoProcessor.highlightsInsideVisiblePartAreProduced( myHighlightingSession, toApplyInside, myPriorityRange, myRestrictRange, getId()); } List<HighlightInfo> toApply = new ArrayList<HighlightInfo>(); for (HighlightInfo info : gotHighlights) { if (!myRestrictRange.containsRange(info.getStartOffset(), info.getEndOffset())) continue; if (!myPriorityRange.containsRange(info.getStartOffset(), info.getEndOffset())) { toApply.add(info); } } toApply.addAll(injectionsOutside); myHighlightInfoProcessor.highlightsOutsideVisiblePartAreProduced( myHighlightingSession, toApply, myRestrictRange, new ProperTextRange(0, myDocument.getTextLength()), getId()); } else { // else apply only result (by default apply command) and only within inside myHighlights.addAll(gotHighlights); myHighlightInfoProcessor.highlightsInsideVisiblePartAreProduced( myHighlightingSession, myHighlights, myRestrictRange, myRestrictRange, getId()); } }
public boolean preprocessUsages(final Ref<UsageInfo[]> refUsages) { UsageInfo[] usagesIn = refUsages.get(); MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>(); RenameUtil.addConflictDescriptions(usagesIn, conflicts); RenamePsiElementProcessor.forElement(myPrimaryElement) .findExistingNameConflicts(myPrimaryElement, myNewName, conflicts); if (!conflicts.isEmpty()) { if (ApplicationManager.getApplication().isUnitTestMode()) { throw new ConflictsInTestsException(conflicts.values()); } ConflictsDialog conflictsDialog = prepareConflictsDialog(conflicts, refUsages.get()); conflictsDialog.show(); if (!conflictsDialog.isOK()) { if (conflictsDialog.isShowConflicts()) prepareSuccessful(); return false; } } final List<UsageInfo> variableUsages = new ArrayList<UsageInfo>(); if (!myRenamers.isEmpty()) { if (!findRenamedVariables(variableUsages)) return false; final LinkedHashMap<PsiElement, String> renames = new LinkedHashMap<PsiElement, String>(); for (final AutomaticRenamer renamer : myRenamers) { final List<? extends PsiNamedElement> variables = renamer.getElements(); for (final PsiNamedElement variable : variables) { final String newName = renamer.getNewName(variable); if (newName != null) { addElement(variable, newName); prepareRenaming(variable, newName, renames); } } } if (!renames.isEmpty()) { myAllRenames.putAll(renames); final Runnable runnable = new Runnable() { public void run() { for (Map.Entry<PsiElement, String> entry : renames.entrySet()) { final UsageInfo[] usages = RenameUtil.findUsages( entry.getKey(), entry.getValue(), mySearchInComments, mySearchTextOccurrences, myAllRenames); Collections.addAll(variableUsages, usages); } } }; if (!ProgressManager.getInstance() .runProcessWithProgressSynchronously( runnable, RefactoringBundle.message("searching.for.variables"), true, myProject)) { return false; } } } final Set<UsageInfo> usagesSet = new HashSet<UsageInfo>(Arrays.asList(usagesIn)); usagesSet.addAll(variableUsages); final List<UnresolvableCollisionUsageInfo> conflictUsages = RenameUtil.removeConflictUsages(usagesSet); if (conflictUsages != null) { mySkippedUsages.addAll(conflictUsages); } refUsages.set(usagesSet.toArray(new UsageInfo[usagesSet.size()])); prepareSuccessful(); return true; }
/** * If setting indicates, move all overloaded methods (of the same name) adjacent with the first * encountered. Sort in the configured order (original order, or by number of parameters). */ public static void handleOverloadedMethods( List<ClassContentsEntry> contents, RearrangerSettings settings) { if (!settings.isKeepOverloadedMethodsTogether()) return; /** * first, detect overloaded methods and move them to the first method's list of overloaded * methods. Make two passes, first for extracted methods, then for non-extracted methods. This * will organize any overloaded methods for extracted methods with them (as opposed to whichever * was seen first.) */ cullOverloadedMethods(contents, true); LOG.debug("entered handleOverloadedMethods(): move overloaded methods together"); cullOverloadedMethods(contents, false); List<ClassContentsEntry> copy = new ArrayList<ClassContentsEntry>(contents); for (ClassContentsEntry rangeEntry : copy) { if (rangeEntry instanceof RelatableEntry) { MethodEntry current = (MethodEntry) rangeEntry; if (current.myOverloadedMethods.size() > 0) { List<MethodEntry> newList = new ArrayList<MethodEntry>(current.myOverloadedMethods.size() + 1); newList.add(current); /** * we are looking at the head of a list of overloaded methods. We need to sort the list if * necessary and, if the head of the list has changed, replace it in the contents array. */ switch (settings.getOverloadedOrder()) { case RearrangerSettings.OVERLOADED_ORDER_RETAIN_ORIGINAL: // list is already in original order, except perhaps that the top-most extracted // method // comes first (if there is one). newList.addAll(current.myOverloadedMethods); break; case RearrangerSettings.OVERLOADED_ORDER_ASCENDING_PARAMETERS: case RearrangerSettings.OVERLOADED_ORDER_DESCENDING_PARAMETERS: for (MethodEntry entry : current.myOverloadedMethods) { boolean inserted = false; for (int index = 0; index < newList.size(); index++) { MethodEntry me = newList.get(index); if (settings.getOverloadedOrder() == RearrangerSettings.OVERLOADED_ORDER_ASCENDING_PARAMETERS ? me.getnParameters() > entry.getnParameters() : me.getnParameters() < entry.getnParameters()) { newList.add(index, entry); inserted = true; break; } } if (!inserted) { newList.add(entry); } } break; } current.myOverloadedMethods.clear(); /** * if the head of the arraylist is not the same as "current", then the sort operation * moved another method to the head of the list. Replace that in the contents array. Then * assign a new ordered list. */ int index = contents.indexOf(current); if (newList.get(0) != current) { contents.set(index, ((MethodEntry) newList.get(0))); } /** insert the remaining overloaded methods after the current entry. */ newList.remove(0); for (int j = 0; j < newList.size(); j++) { contents.add(index + j + 1, ((MethodEntry) newList.get(j))); } } } } }
public void addAllPersistentEntries(EntryPointsManagerBase manager) { myPersistentEntryPoints.putAll(manager.myPersistentEntryPoints); myPatterns.addAll(manager.getPatterns()); }
@NotNull public Class classToClass(@NotNull PsiClass psiClass) { Set<String> modifiers = modifiersListToModifiersSet(psiClass.getModifierList()); List<Field> fields = fieldsToFieldList(psiClass.getFields(), psiClass); List<Element> typeParameters = elementsToElementList(psiClass.getTypeParameters()); List<Type> implementsTypes = typesToNotNullableTypeList(psiClass.getImplementsListTypes()); List<Type> extendsTypes = typesToNotNullableTypeList(psiClass.getExtendsListTypes()); IdentifierImpl name = new IdentifierImpl(psiClass.getName()); List<Expression> baseClassParams = new LinkedList<Expression>(); List<Member> members = getMembers(psiClass); // we try to find super() call and generate class declaration like that: class A(name: String, i // : Int) : Base(name) SuperVisitor visitor = new SuperVisitor(); psiClass.accept(visitor); Collection<PsiExpressionList> resolvedSuperCallParameters = visitor.getResolvedSuperCallParameters(); if (resolvedSuperCallParameters.size() == 1) { baseClassParams.addAll( expressionsToExpressionList( resolvedSuperCallParameters.toArray(new PsiExpressionList[1])[0].getExpressions())); } // we create primary constructor from all non final fields and fields without initializers if (!psiClass.isEnum() && !psiClass.isInterface() && psiClass.getConstructors().length > 1 && getPrimaryConstructorForThisCase(psiClass) == null) { List<Field> finalOrWithEmptyInitializer = getFinalOrWithEmptyInitializer(fields); Map<String, String> initializers = new HashMap<String, String>(); for (Member m : members) { // and modify secondaries if (m.getKind() == INode.Kind.CONSTRUCTOR) { Function f = (Function) m; if (!((Constructor) f).isPrimary()) { for (Field fo : finalOrWithEmptyInitializer) { String init = getDefaultInitializer(fo); initializers.put(fo.getIdentifier().toKotlin(), init); } List<Statement> newStatements = new LinkedList<Statement>(); for (Statement s : f.getBlock().getStatements()) { boolean isRemoved = false; if (s.getKind() == INode.Kind.ASSIGNMENT_EXPRESSION) { AssignmentExpression assignmentExpression = (AssignmentExpression) s; if (assignmentExpression.getLeft().getKind() == INode.Kind.CALL_CHAIN) { for (Field fo : finalOrWithEmptyInitializer) { String id = fo.getIdentifier().toKotlin(); if (((CallChainExpression) assignmentExpression.getLeft()) .getIdentifier() .toKotlin() .endsWith("." + id)) { initializers.put(id, assignmentExpression.getRight().toKotlin()); isRemoved = true; } } } } if (!isRemoved) { newStatements.add(s); } } newStatements.add( 0, new DummyStringExpression( "val __ = " + createPrimaryConstructorInvocation( name.toKotlin(), finalOrWithEmptyInitializer, initializers))); f.setBlock(new Block(newStatements)); } } } members.add( new Constructor( Identifier.EMPTY_IDENTIFIER, Collections.<String>emptySet(), new ClassType(name), Collections.<Element>emptyList(), new ParameterList(createParametersFromFields(finalOrWithEmptyInitializer)), new Block(createInitStatementsFromFields(finalOrWithEmptyInitializer)), true)); } if (psiClass.isInterface()) { return new Trait( this, name, modifiers, typeParameters, extendsTypes, Collections.<Expression>emptyList(), implementsTypes, members); } if (psiClass.isEnum()) { return new Enum( this, name, modifiers, typeParameters, Collections.<Type>emptyList(), Collections.<Expression>emptyList(), implementsTypes, members); } return new Class( this, name, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, members); }