private void collectUncaughtExceptions(@NotNull PsiMethod method) {
    if (isExternalOverride()) return;
    if (getRefManager().isOfflineView()) return;
    @NonNls final String name = method.getName();
    if (getOwnerClass().isTestCase() && name.startsWith("test")) return;

    if (getSuperMethods().isEmpty()) {
      PsiClassType[] throwsList = method.getThrowsList().getReferencedTypes();
      if (throwsList.length > 0) {
        myUnThrownExceptions =
            throwsList.length == 1
                ? new SmartList<String>()
                : new ArrayList<String>(throwsList.length);
        for (final PsiClassType type : throwsList) {
          PsiClass aClass = type.resolve();
          String fqn = aClass == null ? null : aClass.getQualifiedName();
          if (fqn != null) {
            myUnThrownExceptions.add(fqn);
          }
        }
      }
    }

    final PsiCodeBlock body = method.getBody();
    if (body == null) return;

    final Collection<PsiClassType> exceptionTypes =
        ExceptionUtil.collectUnhandledExceptions(body, method, false);
    for (final PsiClassType exceptionType : exceptionTypes) {
      updateThrowsList(exceptionType);
    }
  }
  @NotNull
  private static Set<PsiClassType> filterInProjectExceptions(
      @Nullable PsiMethod targetMethod, @NotNull List<PsiClassType> unhandledExceptions) {
    if (targetMethod == null) return Collections.emptySet();

    Set<PsiClassType> result = new HashSet<PsiClassType>();

    if (targetMethod.getManager().isInProject(targetMethod)) {
      PsiMethod[] superMethods = targetMethod.findSuperMethods();
      for (PsiMethod superMethod : superMethods) {
        Set<PsiClassType> classTypes = filterInProjectExceptions(superMethod, unhandledExceptions);
        result.addAll(classTypes);
      }

      if (superMethods.length == 0) {
        result.addAll(unhandledExceptions);
      }
    } else {
      PsiClassType[] referencedTypes = targetMethod.getThrowsList().getReferencedTypes();
      for (PsiClassType referencedType : referencedTypes) {
        PsiClass psiClass = referencedType.resolve();
        if (psiClass == null) continue;
        for (PsiClassType exception : unhandledExceptions) {
          if (referencedType.isAssignableFrom(exception)) result.add(exception);
        }
      }
    }

    return result;
  }
  @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 static ThrownExceptionInfo[] generateExceptionInfos(
     PsiMethod method, ThrownExceptionInfo[] newExceptions) {
   final PsiClassType[] exceptions = method.getThrowsList().getReferencedTypes();
   ThrownExceptionInfo[] result =
       new ThrownExceptionInfo[exceptions.length + newExceptions.length];
   for (int i = 0; i < exceptions.length; i++) {
     result[i] = new JavaThrownExceptionInfo(i);
   }
   System.arraycopy(newExceptions, 0, result, exceptions.length, newExceptions.length);
   return result;
 }
 private static boolean isThrowsCompatible(PsiMethod method) {
   return ContainerUtil.find(
           method.getThrowsList().getReferencedTypes(),
           new Condition<PsiClassType>() {
             @Override
             public boolean value(PsiClassType type) {
               return !ExceptionUtil.isUncheckedException(type);
             }
           })
       != null;
 }
  private static void processCallerMethod(
      JavaChangeInfo changeInfo,
      PsiMethod caller,
      PsiMethod baseMethod,
      boolean toInsertParams,
      boolean toInsertThrows)
      throws IncorrectOperationException {
    LOG.assertTrue(toInsertParams || toInsertThrows);
    if (toInsertParams) {
      List<PsiParameter> newParameters = new ArrayList<PsiParameter>();
      ContainerUtil.addAll(newParameters, caller.getParameterList().getParameters());
      final JavaParameterInfo[] primaryNewParms = changeInfo.getNewParameters();
      PsiSubstitutor substitutor =
          baseMethod == null
              ? PsiSubstitutor.EMPTY
              : ChangeSignatureProcessor.calculateSubstitutor(caller, baseMethod);
      for (JavaParameterInfo info : primaryNewParms) {
        if (info.getOldIndex() < 0)
          newParameters.add(createNewParameter(changeInfo, info, substitutor));
      }
      PsiParameter[] arrayed = newParameters.toArray(new PsiParameter[newParameters.size()]);
      boolean[] toRemoveParm = new boolean[arrayed.length];
      Arrays.fill(toRemoveParm, false);
      resolveParameterVsFieldsConflicts(arrayed, caller, caller.getParameterList(), toRemoveParm);
    }

    if (toInsertThrows) {
      List<PsiJavaCodeReferenceElement> newThrowns = new ArrayList<PsiJavaCodeReferenceElement>();
      final PsiReferenceList throwsList = caller.getThrowsList();
      ContainerUtil.addAll(newThrowns, throwsList.getReferenceElements());
      final ThrownExceptionInfo[] primaryNewExns = changeInfo.getNewExceptions();
      for (ThrownExceptionInfo thrownExceptionInfo : primaryNewExns) {
        if (thrownExceptionInfo.getOldIndex() < 0) {
          final PsiClassType type =
              (PsiClassType) thrownExceptionInfo.createType(caller, caller.getManager());
          final PsiJavaCodeReferenceElement ref =
              JavaPsiFacade.getInstance(caller.getProject())
                  .getElementFactory()
                  .createReferenceElementByType(type);
          newThrowns.add(ref);
        }
      }
      PsiJavaCodeReferenceElement[] arrayed =
          newThrowns.toArray(new PsiJavaCodeReferenceElement[newThrowns.size()]);
      boolean[] toRemoveParm = new boolean[arrayed.length];
      Arrays.fill(toRemoveParm, false);
      ChangeSignatureUtil.synchronizeList(
          throwsList, Arrays.asList(arrayed), ThrowsList.INSTANCE, toRemoveParm);
    }
  }
  private static void processMethod(
      @NotNull Project project,
      @NotNull PsiMethod targetMethod,
      @NotNull Set<PsiClassType> unhandledExceptions)
      throws IncorrectOperationException {
    for (PsiClassType unhandledException : unhandledExceptions) {
      PsiClass exceptionClass = unhandledException.resolve();
      if (exceptionClass != null) {
        PsiUtil.addException(targetMethod, exceptionClass);
      }
    }

    CodeStyleManager.getInstance(project).reformat(targetMethod.getThrowsList());
  }
  private static boolean hasSuperMethodsWithoutExceptions(
      @NotNull PsiMethod[] superMethods, @NotNull Set<PsiClassType> unhandledExceptions) {
    for (PsiMethod superMethod : superMethods) {
      PsiClassType[] referencedTypes = superMethod.getThrowsList().getReferencedTypes();

      Set<PsiClassType> exceptions = new HashSet<PsiClassType>(unhandledExceptions);
      for (PsiClassType referencedType : referencedTypes) {
        for (PsiClassType exception : unhandledExceptions) {
          if (referencedType.isAssignableFrom(exception)) exceptions.remove(exception);
        }
      }

      if (!exceptions.isEmpty()) return true;
    }

    return false;
  }
  private static void fixPrimaryThrowsLists(PsiMethod method, PsiClassType[] newExceptions)
      throws IncorrectOperationException {
    PsiElementFactory elementFactory =
        JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
    PsiJavaCodeReferenceElement[] refs = new PsiJavaCodeReferenceElement[newExceptions.length];
    for (int i = 0; i < refs.length; i++) {
      refs[i] = elementFactory.createReferenceElementByType(newExceptions[i]);
    }
    PsiReferenceList throwsList = elementFactory.createReferenceList(refs);

    PsiReferenceList methodThrowsList =
        (PsiReferenceList) method.getThrowsList().replace(throwsList);
    methodThrowsList =
        (PsiReferenceList)
            JavaCodeStyleManager.getInstance(method.getProject())
                .shortenClassReferences(methodThrowsList);
    CodeStyleManager.getInstance(method.getManager().getProject())
        .reformatRange(
            method,
            method.getParameterList().getTextRange().getEndOffset(),
            methodThrowsList.getTextRange().getEndOffset());
  }
  public static PsiMethod generateConstructorPrototype(
      PsiClass aClass, PsiMethod baseConstructor, boolean copyJavaDoc, PsiField[] fields)
      throws IncorrectOperationException {
    PsiManager manager = aClass.getManager();
    JVMElementFactory factory =
        JVMElementFactories.requireFactory(aClass.getLanguage(), aClass.getProject());
    CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject());

    PsiMethod constructor = factory.createConstructor(aClass.getName(), aClass);
    String modifier = PsiUtil.getMaximumModifierForMember(aClass, false);

    if (modifier != null) {
      PsiUtil.setModifierProperty(constructor, modifier, true);
    }

    if (baseConstructor != null) {
      PsiJavaCodeReferenceElement[] throwRefs =
          baseConstructor.getThrowsList().getReferenceElements();
      for (PsiJavaCodeReferenceElement ref : throwRefs) {
        constructor.getThrowsList().add(ref);
      }

      if (copyJavaDoc) {
        final PsiDocComment docComment =
            ((PsiMethod) baseConstructor.getNavigationElement()).getDocComment();
        if (docComment != null) {
          constructor.addAfter(docComment, null);
        }
      }
    }

    boolean isNotEnum = false;
    if (baseConstructor != null) {
      PsiClass superClass = aClass.getSuperClass();
      LOG.assertTrue(superClass != null);
      if (!CommonClassNames.JAVA_LANG_ENUM.equals(superClass.getQualifiedName())) {
        isNotEnum = true;
        if (baseConstructor instanceof PsiCompiledElement) { // to get some parameter names
          PsiClass dummyClass =
              JVMElementFactories.requireFactory(
                      baseConstructor.getLanguage(), baseConstructor.getProject())
                  .createClass("Dummy");
          baseConstructor = (PsiMethod) dummyClass.add(baseConstructor);
        }
        PsiParameter[] params = baseConstructor.getParameterList().getParameters();
        for (PsiParameter param : params) {
          PsiParameter newParam = factory.createParameter(param.getName(), param.getType(), aClass);
          GenerateMembersUtil.copyOrReplaceModifierList(param, newParam);
          constructor.getParameterList().add(newParam);
        }
      }
    }

    JavaCodeStyleManager javaStyle = JavaCodeStyleManager.getInstance(aClass.getProject());

    final PsiMethod dummyConstructor = factory.createConstructor(aClass.getName());
    dummyConstructor.getParameterList().replace(constructor.getParameterList().copy());
    List<PsiParameter> fieldParams = new ArrayList<PsiParameter>();
    for (PsiField field : fields) {
      String fieldName = field.getName();
      String name = javaStyle.variableNameToPropertyName(fieldName, VariableKind.FIELD);
      String parmName = javaStyle.propertyNameToVariableName(name, VariableKind.PARAMETER);
      parmName = javaStyle.suggestUniqueVariableName(parmName, dummyConstructor, true);
      PsiParameter parm = factory.createParameter(parmName, field.getType(), aClass);

      final NullableNotNullManager nullableManager =
          NullableNotNullManager.getInstance(field.getProject());
      final String notNull = nullableManager.getNotNull(field);
      if (notNull != null) {
        parm.getModifierList()
            .addAfter(factory.createAnnotationFromText("@" + notNull, field), null);
      }

      constructor.getParameterList().add(parm);
      dummyConstructor.getParameterList().add(parm.copy());
      fieldParams.add(parm);
    }

    ConstructorBodyGenerator generator =
        ConstructorBodyGenerator.INSTANCE.forLanguage(aClass.getLanguage());
    if (generator != null) {
      @NonNls StringBuilder buffer = new StringBuilder();
      generator.start(buffer, constructor.getName(), PsiParameter.EMPTY_ARRAY);
      if (isNotEnum) {
        generator.generateSuperCallIfNeeded(
            buffer, baseConstructor.getParameterList().getParameters());
      }
      generator.generateFieldInitialization(
          buffer, fields, fieldParams.toArray(new PsiParameter[fieldParams.size()]));
      generator.finish(buffer);
      PsiMethod stub = factory.createMethodFromText(buffer.toString(), aClass);
      constructor.getBody().replace(stub.getBody());
    }

    constructor = (PsiMethod) codeStyleManager.reformat(constructor);
    return constructor;
  }
 private static PsiClassType[] getCalleeChangedExceptionInfo(final PsiMethod callee) {
   return callee
       .getThrowsList()
       .getReferencedTypes(); // Callee method's throws list is already modified!
 }
Пример #12
0
  public SNode convertMethod(PsiMethod x, SNode parentConcept) {
    SNode method;

    if (x.isConstructor()) {
      method =
          SConceptOperations.createNewNode(
              "jetbrains.mps.baseLanguage.structure.ConstructorDeclaration", null);

    } else if (x instanceof PsiAnnotationMethod
        && SConceptOperations.isSubConceptOf(
            parentConcept, "jetbrains.mps.baseLanguage.structure.Annotation")) {
      method =
          SConceptOperations.createNewNode(
              "jetbrains.mps.baseLanguage.structure.AnnotationMethodDeclaration", null);

      if (((PsiAnnotationMethod) x).getDefaultValue() != null) {
        SNode str =
            SConceptOperations.createNewNode(
                "jetbrains.mps.baseLanguage.structure.StringLiteral", null);
        SPropertyOperations.set(str, "value", "TODO: SUPPORT EXPRESSIONS IN PSI STUBS?");
        SLinkOperations.setTarget(
            SNodeOperations.cast(
                method, "jetbrains.mps.baseLanguage.structure.AnnotationMethodDeclaration"),
            "defaultValue",
            str,
            true);
      }

    } else if (!(isStatic(x))
        || SConceptOperations.isSubConceptOf(
            parentConcept, "jetbrains.mps.baseLanguage.structure.Interface")) {
      method =
          SConceptOperations.createNewNode(
              "jetbrains.mps.baseLanguage.structure.InstanceMethodDeclaration", null);

    } else {
      method =
          SConceptOperations.createNewNode(
              "jetbrains.mps.baseLanguage.structure.StaticMethodDeclaration", null);
    }

    SPropertyOperations.set(method, "name", x.getName());
    SLinkOperations.setTarget(
        SNodeOperations.cast(method, "jetbrains.mps.baseLanguage.structure.ClassifierMember"),
        "visibility",
        getVisibility(x),
        true);
    SPropertyOperations.set(method, "isFinal", "" + (isFinal(x)));
    SPropertyOperations.set(
        method, "isSynchronized", "" + (x.hasModifierProperty(PsiModifier.SYNCHRONIZED)));

    SLinkOperations.setTarget(method, "returnType", convertType(x.getReturnType()), true);
    ListSequence.fromList(SLinkOperations.getTargets(method, "parameter", true))
        .addSequence(
            Sequence.fromIterable(Sequence.fromArray(x.getParameterList().getParameters()))
                .select(
                    new ISelector<PsiParameter, SNode>() {
                      public SNode select(PsiParameter it) {
                        SNode param =
                            SConceptOperations.createNewNode(
                                "jetbrains.mps.baseLanguage.structure.ParameterDeclaration", null);
                        SPropertyOperations.set(param, "name", it.getName());
                        SLinkOperations.setTarget(param, "type", convertType(it.getType()), true);
                        SPropertyOperations.set(param, "isFinal", "" + (isFinal(it)));

                        addAnnotations(it, param);

                        return param;
                      }
                    }));

    ListSequence.fromList(SLinkOperations.getTargets(method, "throwsItem", true))
        .addSequence(
            Sequence.fromIterable(Sequence.fromArray(x.getThrowsList().getReferencedTypes()))
                .select(
                    new ISelector<PsiClassType, SNode>() {
                      public SNode select(PsiClassType it) {
                        SNode typ = resolveClass(it);
                        return typ;
                      }
                    }));

    addTypeParams(x, method);

    // not strictly necessary
    if (x.getBody() != null) {
      SLinkOperations.setTarget(
          method,
          "body",
          SConceptOperations.createNewNode(
              "jetbrains.mps.baseLanguage.structure.StubStatementList", null),
          true);
    } else {
      SLinkOperations.setTarget(
          method,
          "body",
          SConceptOperations.createNewNode(
              "jetbrains.mps.baseLanguage.structure.StatementList", null),
          true);
    }

    return method;
  }
  @Override
  @Nullable
  public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) {
    if (element instanceof GrVariable || element instanceof GrImplicitVariable) {
      StringBuilder buffer = new StringBuilder();
      PsiVariable variable = (PsiVariable) element;

      if (originalElement instanceof GrVariableDeclaration
          && ((GrVariableDeclaration) originalElement).getVariables().length > 1) {
        for (GrVariable var : ((GrVariableDeclaration) originalElement).getVariables()) {
          generateVariableInfo(originalElement, buffer, var);
          buffer.append("\n\n");
        }
      } else {
        generateVariableInfo(originalElement, buffer, variable);
      }
      return buffer.toString();
    } else if (element instanceof PsiMethod) {
      StringBuilder buffer = new StringBuilder();
      PsiMethod method = (PsiMethod) element;
      if (method instanceof GrGdkMethod) {
        buffer.append("[GDK] ");
      } else {
        PsiClass hisClass = method.getContainingClass();
        if (hisClass != null) {
          String qName = hisClass.getQualifiedName();
          if (qName != null) {
            buffer.append(qName).append("\n");
          }
        }
      }

      PsiSubstitutor substitutor = calcSubstitutor(originalElement);
      if (!method.isConstructor()) {
        final PsiType substituted = substitutor.substitute(PsiUtil.getSmartReturnType(method));
        PsiImplUtil.appendTypeString(buffer, substituted, originalElement);
        buffer.append(" ");
      }
      buffer.append(method.getName()).append(" ");
      buffer.append("(");
      PsiParameter[] parameters = method.getParameterList().getParameters();
      for (int i = 0; i < parameters.length; i++) {
        PsiParameter parameter = parameters[i];
        if (i > 0) buffer.append(", ");
        if (parameter instanceof GrParameter) {
          GroovyPresentationUtil.appendParameterPresentation(
              (GrParameter) parameter, substitutor, TypePresentation.LINK, buffer);
        } else {
          PsiType type = parameter.getType();
          PsiImplUtil.appendTypeString(buffer, substitutor.substitute(type), originalElement);
          buffer.append(" ");
          buffer.append(parameter.getName());
        }
      }
      buffer.append(")");
      final PsiClassType[] referencedTypes = method.getThrowsList().getReferencedTypes();
      if (referencedTypes.length > 0) {
        buffer.append("\nthrows ");
        for (PsiClassType referencedType : referencedTypes) {
          PsiImplUtil.appendTypeString(buffer, referencedType, originalElement);
          buffer.append(", ");
        }
        buffer.delete(buffer.length() - 2, buffer.length());
      }
      return buffer.toString();
    } else if (element instanceof GrTypeDefinition) {
      return generateClassInfo((GrTypeDefinition) element);
    }

    return null;
  }