private static boolean isMethodDeclarationInSource(@NotNull PsiMethod psiMethod) { if (psiMethod.getContainingFile() == null) return false; final VirtualFile virtualFile = psiMethod.getContainingFile().getVirtualFile(); if (virtualFile == null) return false; return ProjectRootManager.getInstance(psiMethod.getProject()) .getFileIndex() .isInSource(virtualFile); }
static void addExceptionsToThrowsList( @NotNull final Project project, @NotNull final PsiMethod targetMethod, @NotNull final Set<PsiClassType> unhandledExceptions) { final PsiMethod[] superMethods = getSuperMethods(targetMethod); boolean hasSuperMethodsWithoutExceptions = hasSuperMethodsWithoutExceptions(superMethods, unhandledExceptions); final boolean processSuperMethods; if (hasSuperMethodsWithoutExceptions && superMethods.length > 0) { int result = ApplicationManager.getApplication().isUnitTestMode() ? Messages.YES : Messages.showYesNoCancelDialog( QuickFixBundle.message( "add.exception.to.throws.inherited.method.warning.text", targetMethod.getName()), QuickFixBundle.message("method.is.inherited.warning.title"), Messages.getQuestionIcon()); if (result == Messages.YES) { processSuperMethods = true; } else if (result == Messages.NO) { processSuperMethods = false; } else { return; } } else { processSuperMethods = false; } ApplicationManager.getApplication() .runWriteAction( () -> { if (!FileModificationService.getInstance() .prepareFileForWrite(targetMethod.getContainingFile())) return; if (processSuperMethods) { for (PsiMethod superMethod : superMethods) { if (!FileModificationService.getInstance() .prepareFileForWrite(superMethod.getContainingFile())) return; } } try { processMethod(project, targetMethod, unhandledExceptions); if (processSuperMethods) { for (PsiMethod superMethod : superMethods) { processMethod(project, superMethod, unhandledExceptions); } } } catch (IncorrectOperationException e) { LOG.error(e); } }); }
public PsiReturnStatement addReturnForMethod(final PsiFile file, final PsiMethod method) { final PsiModifierList modifiers = method.getModifierList(); if (modifiers.hasModifierProperty(PsiModifier.ABSTRACT) || method.getBody() == null) { return null; } try { final ConvertReturnStatementsVisitor visitor = new ConvertReturnStatementsVisitor(factory, method, myTargetType); ControlFlow controlFlow; try { controlFlow = HighlightControlFlowUtil.getControlFlowNoConstantEvaluate(method.getBody()); } catch (AnalysisCanceledException e) { return null; // must be an error } PsiReturnStatement returnStatement; if (controlFlow != null && ControlFlowUtil.processReturns(controlFlow, visitor)) { // extra return statement not needed // get latest modified return statement and select... returnStatement = visitor.getLatestReturn(); } else { returnStatement = visitor.createReturnInLastStatement(); } if (method.getContainingFile() != file) { UndoUtil.markPsiFileForUndo(file); } return returnStatement; } catch (IncorrectOperationException e) { LOG.error(e); } return null; }
protected final void registerMethodError(@NotNull PsiMethod method, Object... infos) { final PsiElement nameIdentifier = method.getNameIdentifier(); if (nameIdentifier == null) { registerError(method.getContainingFile(), infos); } else { registerError(nameIdentifier, infos); } }
private static Editor getEditorForMethod( PsiMethod myMethod, @NotNull final Project project, final Editor editor, final PsiFile file) { PsiFile containingFile = myMethod.getContainingFile(); if (containingFile != file) { OpenFileDescriptor descriptor = new OpenFileDescriptor(project, containingFile.getVirtualFile()); return FileEditorManager.getInstance(project).openTextEditor(descriptor, true); } return editor; }
@Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) { if (!CodeInsightUtilBase.prepareFileForWrite(myMethod.getContainingFile())) return; try { PsiUtil.setModifierProperty(myMethod, PsiModifier.ABSTRACT, false); CreateFromUsageUtils.setupMethodBody(myMethod); CreateFromUsageUtils.setupEditor(myMethod, editor); } catch (IncorrectOperationException e) { LOG.error(e); } }
@Override public void invoke( @NotNull Project project, @NotNull PsiFile file, Editor editor, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { final PsiMethod myMethod = (PsiMethod) startElement; if (!FileModificationService.getInstance().prepareFileForWrite(myMethod.getContainingFile())) return; final PsiType myReturnType = myReturnTypePointer.getType(); if (myReturnType == null) return; if (myFixWholeHierarchy) { final PsiMethod superMethod = myMethod.findDeepestSuperMethod(); final PsiType superReturnType = superMethod == null ? null : superMethod.getReturnType(); if (superReturnType != null && !Comparing.equal(myReturnType, superReturnType) && !changeClassTypeArgument( myMethod, project, superReturnType, superMethod.getContainingClass(), editor, myReturnType)) { return; } } final List<PsiMethod> affectedMethods = changeReturnType(myMethod, myReturnType); PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); PsiReturnStatement statementToSelect = null; if (!PsiType.VOID.equals(myReturnType)) { final ReturnStatementAdder adder = new ReturnStatementAdder(factory, myReturnType); for (PsiMethod affectedMethod : affectedMethods) { PsiReturnStatement statement = adder.addReturnForMethod(file, affectedMethod); if (statement != null && affectedMethod == myMethod) { statementToSelect = statement; } } } if (statementToSelect != null) { Editor editorForMethod = getEditorForMethod(myMethod, project, editor, statementToSelect.getContainingFile()); if (editorForMethod != null) { selectReturnValueInEditor(statementToSelect, editorForMethod); } } }
@Override protected boolean preprocessUsages(@NotNull final Ref<UsageInfo[]> refUsages) { MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>(); if (myUseExistingClass) { if (existingClass == null) { conflicts.putValue( null, RefactorJBundle.message("cannot.perform.the.refactoring") + "Could not find the selected class"); } if (myExistingClassCompatibleConstructor == null) { conflicts.putValue( existingClass, RefactorJBundle.message("cannot.perform.the.refactoring") + "Selected class has no compatible constructors"); } } else { if (existingClass != null) { conflicts.putValue( existingClass, RefactorJBundle.message("cannot.perform.the.refactoring") + RefactorJBundle.message("there.already.exists.a.class.with.the.chosen.name")); } if (myMoveDestination != null) { if (!myMoveDestination.isTargetAccessible( myProject, method.getContainingFile().getVirtualFile())) { conflicts.putValue(method, "Created class won't be accessible"); } } } for (UsageInfo usageInfo : refUsages.get()) { if (usageInfo instanceof FixableUsageInfo) { final String conflictMessage = ((FixableUsageInfo) usageInfo).getConflictMessage(); if (conflictMessage != null) { conflicts.putValue(usageInfo.getElement(), conflictMessage); } } } return showConflicts(conflicts, refUsages.get()); }
@NotNull private List<PsiMethod> getMethodsToImport() { PsiShortNamesCache cache = PsiShortNamesCache.getInstance(myMethodCall.getProject()); PsiMethodCallExpression element = myMethodCall.getElement(); PsiReferenceExpression reference = element.getMethodExpression(); PsiExpressionList argumentList = element.getArgumentList(); String name = reference.getReferenceName(); List<PsiMethod> list = new ArrayList<PsiMethod>(); if (name == null) return list; GlobalSearchScope scope = element.getResolveScope(); PsiMethod[] methods = cache.getMethodsByNameIfNotMoreThan(name, scope, 20); List<PsiMethod> applicableList = new ArrayList<PsiMethod>(); final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(element.getProject()).getResolveHelper(); for (PsiMethod method : methods) { ProgressManager.checkCanceled(); if (JavaCompletionUtil.isInExcludedPackage(method)) continue; if (!method.hasModifierProperty(PsiModifier.STATIC)) continue; PsiFile file = method.getContainingFile(); if (file instanceof PsiJavaFile // do not show methods from default package && ((PsiJavaFile) file).getPackageName().length() != 0 && PsiUtil.isAccessible(method, element, method.getContainingClass())) { list.add(method); PsiSubstitutor substitutorForMethod = resolveHelper.inferTypeArguments( method.getTypeParameters(), method.getParameterList().getParameters(), argumentList.getExpressions(), PsiSubstitutor.EMPTY, element.getParent(), DefaultParameterTypeInferencePolicy.INSTANCE); if (PsiUtil.isApplicable(method, substitutorForMethod, argumentList)) { applicableList.add(method); } } } List<PsiMethod> result = applicableList.isEmpty() ? list : applicableList; for (int i = result.size() - 1; i >= 0; i--) { ProgressManager.checkCanceled(); PsiMethod method = result.get(i); PsiClass containingClass = method.getContainingClass(); for (int j = i + 1; j < result.size(); j++) { PsiMethod exMethod = result.get(j); if (!Comparing.strEqual(exMethod.getName(), method.getName())) continue; PsiClass exContainingClass = exMethod.getContainingClass(); if (containingClass != null && exContainingClass != null && !Comparing.equal( containingClass.getQualifiedName(), exContainingClass.getQualifiedName())) continue; // same named methods, drop one result.remove(i); break; } // check for manually excluded if (isExcluded(method)) { result.remove(i); } } Collections.sort(result, new PsiProximityComparator(argumentList)); return result; }
private PsiClass buildClass() { if (existingClass != null) { return existingClass; } final ParameterObjectBuilder beanClassBuilder = new ParameterObjectBuilder(); beanClassBuilder.setVisibility(myCreateInnerClass ? PsiModifier.PRIVATE : PsiModifier.PUBLIC); beanClassBuilder.setProject(myProject); beanClassBuilder.setTypeArguments(typeParams); beanClassBuilder.setClassName(className); beanClassBuilder.setPackageName(packageName); for (ParameterChunk parameterChunk : parameters) { final VariableData parameter = parameterChunk.parameter; final boolean setterRequired = paramsNeedingSetters.contains(parameter.variable); beanClassBuilder.addField( (PsiParameter) parameter.variable, parameter.name, parameter.type, setterRequired); } final String classString = beanClassBuilder.buildBeanClass(); try { final PsiFileFactory factory = PsiFileFactory.getInstance(method.getProject()); final PsiJavaFile newFile = (PsiJavaFile) factory.createFileFromText(className + ".java", JavaFileType.INSTANCE, classString); if (myCreateInnerClass) { final PsiClass containingClass = method.getContainingClass(); final PsiClass[] classes = newFile.getClasses(); assert classes.length > 0 : classString; final PsiClass innerClass = (PsiClass) containingClass.add(classes[0]); PsiUtil.setModifierProperty(innerClass, PsiModifier.STATIC, true); return (PsiClass) JavaCodeStyleManager.getInstance(newFile.getProject()) .shortenClassReferences(innerClass); } else { final PsiFile containingFile = method.getContainingFile(); final PsiDirectory containingDirectory = containingFile.getContainingDirectory(); final PsiDirectory directory; if (myMoveDestination != null) { directory = myMoveDestination.getTargetDirectory(containingDirectory); } else { final Module module = ModuleUtil.findModuleForPsiElement(containingFile); directory = PackageUtil.findOrCreateDirectoryForPackage( module, packageName, containingDirectory, true, true); } if (directory != null) { final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(method.getManager().getProject()); final PsiElement shortenedFile = JavaCodeStyleManager.getInstance(newFile.getProject()) .shortenClassReferences(newFile); final PsiElement reformattedFile = codeStyleManager.reformat(shortenedFile); return ((PsiJavaFile) directory.add(reformattedFile)).getClasses()[0]; } } } catch (IncorrectOperationException e) { logger.info(e); } return null; }
public static List<ParameterInfoImpl> performChange( final Project project, final Editor editor, final PsiFile file, final PsiMethod method, final int minUsagesNumber, final ParameterInfoImpl[] newParametersInfo, final boolean changeAllUsages, final boolean allowDelegation) { if (!FileModificationService.getInstance().prepareFileForWrite(method.getContainingFile())) return null; final FindUsagesManager findUsagesManager = ((FindManagerImpl) FindManager.getInstance(project)).getFindUsagesManager(); final FindUsagesHandler handler = findUsagesManager.getFindUsagesHandler(method, false); if (handler == null) return null; // on failure or cancel (e.g. cancel of super methods dialog) final JavaMethodFindUsagesOptions options = new JavaMethodFindUsagesOptions(project); options.isImplementingMethods = true; options.isOverridingMethods = true; options.isUsages = true; options.isSearchForTextOccurrences = false; final int[] usagesFound = new int[1]; Runnable runnable = () -> { Processor<UsageInfo> processor = t -> ++usagesFound[0] < minUsagesNumber; handler.processElementUsages(method, processor, options); }; String progressTitle = QuickFixBundle.message("searching.for.usages.progress.title"); if (!ProgressManager.getInstance() .runProcessWithProgressSynchronously(runnable, progressTitle, true, project)) return null; if (ApplicationManager.getApplication().isUnitTestMode() || usagesFound[0] < minUsagesNumber) { ChangeSignatureProcessor processor = new ChangeSignatureProcessor( project, method, false, null, method.getName(), method.getReturnType(), newParametersInfo) { @Override @NotNull protected UsageInfo[] findUsages() { return changeAllUsages ? super.findUsages() : UsageInfo.EMPTY_ARRAY; } @Override protected void performRefactoring(@NotNull UsageInfo[] usages) { CommandProcessor.getInstance().setCurrentCommandName(getCommandName()); super.performRefactoring(usages); } }; processor.run(); ApplicationManager.getApplication().runWriteAction(() -> UndoUtil.markPsiFileForUndo(file)); return Arrays.asList(newParametersInfo); } else { final List<ParameterInfoImpl> parameterInfos = newParametersInfo != null ? new ArrayList<ParameterInfoImpl>(Arrays.asList(newParametersInfo)) : new ArrayList<ParameterInfoImpl>(); final PsiReferenceExpression refExpr = JavaTargetElementEvaluator.findReferenceExpression(editor); JavaChangeSignatureDialog dialog = JavaChangeSignatureDialog.createAndPreselectNew( project, method, parameterInfos, allowDelegation, refExpr); dialog.setParameterInfos(parameterInfos); dialog.show(); return dialog.isOK() ? dialog.getParameters() : null; } }
private void addTypesByVariable( HashSet<PsiType> typesSet, PsiVariable var, PsiFile scopeFile, HashSet<PsiVariable> checkedVariables, int flags, TextRange rangeToIgnore) { if (!checkedVariables.add(var)) return; // System.out.println("analyzing usages of " + var + " in file " + scopeFile); SearchScope searchScope = new LocalSearchScope(scopeFile); if (BitUtil.isSet(flags, CHECK_USAGE) || BitUtil.isSet(flags, CHECK_DOWN)) { for (PsiReference varRef : ReferencesSearch.search(var, searchScope, false)) { PsiElement ref = varRef.getElement(); if (BitUtil.isSet(flags, CHECK_USAGE)) { PsiType type = guessElementTypeFromReference(myMethodPatternMap, ref, rangeToIgnore); if (type != null && !(type instanceof PsiPrimitiveType)) { typesSet.add(type); } } if (BitUtil.isSet(flags, CHECK_DOWN)) { if (ref.getParent() instanceof PsiExpressionList && ref.getParent().getParent() instanceof PsiMethodCallExpression) { // TODO : new PsiExpressionList list = (PsiExpressionList) ref.getParent(); PsiExpression[] args = list.getExpressions(); int argIndex = -1; for (int j = 0; j < args.length; j++) { PsiExpression arg = args[j]; if (arg.equals(ref)) { argIndex = j; break; } } PsiMethodCallExpression methodCall = (PsiMethodCallExpression) list.getParent(); PsiMethod method = (PsiMethod) methodCall.getMethodExpression().resolve(); if (method != null) { PsiParameter[] parameters = method.getParameterList().getParameters(); if (argIndex < parameters.length) { addTypesByVariable( typesSet, parameters[argIndex], method.getContainingFile(), checkedVariables, flags | CHECK_USAGE, rangeToIgnore); } } } } } } if (BitUtil.isSet(flags, CHECK_UP)) { if (var instanceof PsiParameter && var.getParent() instanceof PsiParameterList && var.getParent().getParent() instanceof PsiMethod) { PsiParameterList list = (PsiParameterList) var.getParent(); PsiParameter[] parameters = list.getParameters(); int argIndex = -1; for (int i = 0; i < parameters.length; i++) { PsiParameter parameter = parameters[i]; if (parameter.equals(var)) { argIndex = i; break; } } PsiMethod method = (PsiMethod) var.getParent().getParent(); // System.out.println("analyzing usages of " + method + " in file " + scopeFile); for (PsiReference methodRef : ReferencesSearch.search(method, searchScope, false)) { PsiElement ref = methodRef.getElement(); if (ref.getParent() instanceof PsiMethodCallExpression) { PsiMethodCallExpression methodCall = (PsiMethodCallExpression) ref.getParent(); PsiExpression[] args = methodCall.getArgumentList().getExpressions(); if (args.length <= argIndex) continue; PsiExpression arg = args[argIndex]; if (arg instanceof PsiReferenceExpression) { PsiElement refElement = ((PsiReferenceExpression) arg).resolve(); if (refElement instanceof PsiVariable) { addTypesByVariable( typesSet, (PsiVariable) refElement, scopeFile, checkedVariables, flags | CHECK_USAGE, rangeToIgnore); } } // TODO : constructor } } } } }