コード例 #1
0
 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);
 }
コード例 #2
0
  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);
              }
            });
  }
コード例 #3
0
    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;
    }
コード例 #4
0
 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);
   }
 }
コード例 #5
0
  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;
  }
コード例 #6
0
  @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);
    }
  }
コード例 #7
0
  @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());
 }
コード例 #9
0
 @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;
  }
コード例 #11
0
  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;
    }
  }
コード例 #12
0
  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
          }
        }
      }
    }
  }