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! }
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; }