private static void findTypeParameterExternalUsages( final PsiTypeParameter typeParameter, final Collection<UsageInfo> usages) { PsiTypeParameterListOwner owner = typeParameter.getOwner(); if (owner != null) { final PsiTypeParameterList parameterList = owner.getTypeParameterList(); if (parameterList != null) { final int paramsCount = parameterList.getTypeParameters().length; final int index = parameterList.getTypeParameterIndex(typeParameter); ReferencesSearch.search(owner) .forEach( reference -> { if (reference instanceof PsiJavaCodeReferenceElement) { final PsiReferenceParameterList parameterList1 = ((PsiJavaCodeReferenceElement) reference).getParameterList(); if (parameterList1 != null) { PsiTypeElement[] typeArgs = parameterList1.getTypeParameterElements(); if (typeArgs.length > index) { if (typeArgs.length == 1 && paramsCount > 1 && typeArgs[0].getType() instanceof PsiDiamondType) return true; usages.add( new SafeDeleteReferenceJavaDeleteUsageInfo( typeArgs[index], typeParameter, true)); } } } return true; }); } } }
private static boolean changeClassTypeArgument( PsiMethod myMethod, Project project, PsiType superReturnType, PsiClass superClass, Editor editor, PsiType returnType) { if (superClass == null || !superClass.hasTypeParameters()) return true; final PsiClass superReturnTypeClass = PsiUtil.resolveClassInType(superReturnType); if (superReturnTypeClass == null || !(superReturnTypeClass instanceof PsiTypeParameter || superReturnTypeClass.hasTypeParameters())) return true; final PsiClass derivedClass = myMethod.getContainingClass(); if (derivedClass == null) return true; final PsiReferenceParameterList referenceParameterList = findTypeArgumentsList(superClass, derivedClass); if (referenceParameterList == null) return true; final PsiElement resolve = ((PsiJavaCodeReferenceElement) referenceParameterList.getParent()).resolve(); if (!(resolve instanceof PsiClass)) return true; final PsiClass baseClass = (PsiClass) resolve; if (returnType instanceof PsiPrimitiveType) { returnType = ((PsiPrimitiveType) returnType).getBoxedType(derivedClass); } final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, baseClass, PsiSubstitutor.EMPTY); final PsiType superReturnTypeInBaseClassType = superClassSubstitutor.substitute(superReturnType); final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper(); final PsiSubstitutor psiSubstitutor = resolveHelper.inferTypeArguments( PsiTypesUtil.filterUnusedTypeParameters( superReturnTypeInBaseClassType, baseClass.getTypeParameters()), new PsiType[] {superReturnTypeInBaseClassType}, new PsiType[] {returnType}, PsiUtil.getLanguageLevel(superClass)); final TypeMigrationRules rules = new TypeMigrationRules(); final PsiSubstitutor compoundSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, derivedClass, PsiSubstitutor.EMPTY) .putAll(psiSubstitutor); rules.setBoundScope(new LocalSearchScope(derivedClass)); TypeMigrationProcessor.runHighlightingTypeMigration( project, editor, rules, referenceParameterList, JavaPsiFacade.getElementFactory(project).createType(baseClass, compoundSubstitutor)); return false; }
@Override public void beforeCompletion(@NotNull final CompletionInitializationContext context) { final PsiFile file = context.getFile(); if (file instanceof PsiJavaFile) { JavaCompletionUtil.initOffsets(file, context.getOffsetMap()); autoImport(file, context.getStartOffset() - 1, context.getEditor()); if (context.getCompletionType() == CompletionType.BASIC) { if (semicolonNeeded(context.getEditor(), file, context.getStartOffset())) { context.setDummyIdentifier(CompletionInitializationContext.DUMMY_IDENTIFIER.trim() + ";"); return; } final PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset( file, context.getStartOffset(), PsiJavaCodeReferenceElement.class, false); if (ref != null && !(ref instanceof PsiReferenceExpression)) { if (ref.getParent() instanceof PsiTypeElement) { context.setDummyIdentifier( CompletionInitializationContext.DUMMY_IDENTIFIER.trim() + ";"); } if (JavaSmartCompletionContributor.AFTER_NEW.accepts(ref)) { final PsiReferenceParameterList paramList = ref.getParameterList(); if (paramList != null && paramList.getTextLength() > 0) { context .getOffsetMap() .addOffset( ConstructorInsertHandler.PARAM_LIST_START, paramList.getTextRange().getStartOffset()); context .getOffsetMap() .addOffset( ConstructorInsertHandler.PARAM_LIST_END, paramList.getTextRange().getEndOffset()); } } return; } final PsiElement element = file.findElementAt(context.getStartOffset()); if (psiElement().inside(PsiAnnotation.class).accepts(element)) { return; } context.setDummyIdentifier(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED); } } }
private void markTypeParameterUsages( final PsiClass psiClass, PsiClassType migrationType, PsiReferenceParameterList referenceParameterList, final Map<PsiElement, Pair<PsiReference[], PsiType>> roots) { final PsiSubstitutor[] fullHierarchySubstitutor = { migrationType.resolveGenerics().getSubstitutor() }; RefactoringHierarchyUtil.processSuperTypes( migrationType, new RefactoringHierarchyUtil.SuperTypeVisitor() { @Override public void visitType(PsiType aType) { fullHierarchySubstitutor[0] = fullHierarchySubstitutor[0].putAll( ((PsiClassType) aType).resolveGenerics().getSubstitutor()); } @Override public void visitClass(PsiClass aClass) { // do nothing } }); final PsiClass resolvedClass = (PsiClass) ((PsiJavaCodeReferenceElement) referenceParameterList.getParent()).resolve(); ; LOG.assertTrue(resolvedClass != null); final Set<PsiClass> superClasses = new HashSet<PsiClass>(); superClasses.add(resolvedClass); InheritanceUtil.getSuperClasses(resolvedClass, superClasses, true); for (PsiClass superSuperClass : superClasses) { final TypeParameterSearcher parameterSearcher = new TypeParameterSearcher(superSuperClass.getTypeParameters()); superSuperClass.accept( new JavaRecursiveElementVisitor() { @Override public void visitMethod(final PsiMethod method) { super.visitMethod(method); processMemberType( method, parameterSearcher, psiClass, fullHierarchySubstitutor[0], roots); for (PsiParameter parameter : method.getParameterList().getParameters()) { processMemberType( parameter, parameterSearcher, psiClass, fullHierarchySubstitutor[0], roots); } } @Override public void visitField(final PsiField field) { super.visitField(field); processMemberType( field, parameterSearcher, psiClass, fullHierarchySubstitutor[0], roots); } }); } }
public static int insertClassReference( PsiClass psiClass, PsiFile file, int startOffset, int endOffset) { final Project project = file.getProject(); PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); documentManager.commitAllDocuments(); final PsiManager manager = file.getManager(); final Document document = FileDocumentManager.getInstance().getDocument(file.getViewProvider().getVirtualFile()); final PsiReference reference = file.findReferenceAt(startOffset); if (reference != null) { final PsiElement resolved = reference.resolve(); if (resolved instanceof PsiClass) { if (((PsiClass) resolved).getQualifiedName() == null || manager.areElementsEquivalent(psiClass, resolved)) { return endOffset; } } } String name = psiClass.getName(); if (name == null) { return endOffset; } assert document != null; document.replaceString(startOffset, endOffset, name); int newEndOffset = startOffset + name.length(); final RangeMarker toDelete = insertTemporary(newEndOffset, document, " "); documentManager.commitAllDocuments(); PsiElement element = file.findElementAt(startOffset); if (element instanceof PsiIdentifier) { PsiElement parent = element.getParent(); if (parent instanceof PsiJavaCodeReferenceElement && !((PsiJavaCodeReferenceElement) parent).isQualified() && !(parent.getParent() instanceof PsiPackageStatement)) { PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement) parent; if (psiClass.isValid() && !psiClass.getManager().areElementsEquivalent(psiClass, resolveReference(ref))) { final boolean staticImport = ref instanceof PsiImportStaticReferenceElement; PsiElement newElement; try { newElement = staticImport ? ((PsiImportStaticReferenceElement) ref).bindToTargetClass(psiClass) : ref.bindToElement(psiClass); } catch (IncorrectOperationException e) { return endOffset; // can happen if fqn contains reserved words, for example } final RangeMarker rangeMarker = document.createRangeMarker(newElement.getTextRange()); documentManager.doPostponedOperationsAndUnblockDocument(document); documentManager.commitDocument(document); newElement = CodeInsightUtilCore.findElementInRange( file, rangeMarker.getStartOffset(), rangeMarker.getEndOffset(), PsiJavaCodeReferenceElement.class, JavaLanguage.INSTANCE); rangeMarker.dispose(); if (newElement != null) { newEndOffset = newElement.getTextRange().getEndOffset(); if (!(newElement instanceof PsiReferenceExpression)) { PsiReferenceParameterList parameterList = ((PsiJavaCodeReferenceElement) newElement).getParameterList(); if (parameterList != null) { newEndOffset = parameterList.getTextRange().getStartOffset(); } } if (!staticImport && !psiClass .getManager() .areElementsEquivalent(psiClass, resolveReference((PsiReference) newElement)) && !PsiUtil.isInnerClass(psiClass)) { final String qName = psiClass.getQualifiedName(); if (qName != null) { document.replaceString( newElement.getTextRange().getStartOffset(), newEndOffset, qName); newEndOffset = newElement.getTextRange().getStartOffset() + qName.length(); } } } } } } if (toDelete.isValid()) { document.deleteString(toDelete.getStartOffset(), toDelete.getEndOffset()); } return newEndOffset; }
public static boolean isFreeFromTypeInferenceArgs( final PsiParameter[] methodParameters, final PsiLambdaExpression lambdaExpression, final PsiExpression expression, final PsiSubstitutor subst, final PsiType functionalInterfaceType, final PsiTypeParameter typeParam) { if (expression instanceof PsiCallExpression && ((PsiCallExpression) expression).getTypeArguments().length > 0) return true; if (expression instanceof PsiNewExpression) { final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression) expression).getClassOrAnonymousClassReference(); if (classReference != null) { final PsiReferenceParameterList parameterList = classReference.getParameterList(); if (parameterList != null) { final PsiTypeElement[] typeParameterElements = parameterList.getTypeParameterElements(); if (typeParameterElements.length > 0) { if (!(typeParameterElements[0].getType() instanceof PsiDiamondType)) { return true; } } } } } final PsiParameter[] lambdaParams = lambdaExpression.getParameterList().getParameters(); if (lambdaParams.length != methodParameters.length) return false; final boolean[] independent = {true}; final PsiMethod interfaceMethod = getFunctionalInterfaceMethod(functionalInterfaceType); if (interfaceMethod == null) return false; final TypeParamsChecker paramsChecker = new TypeParamsChecker(lambdaExpression); for (PsiParameter parameter : interfaceMethod.getParameterList().getParameters()) { subst.substitute(parameter.getType()).accept(paramsChecker); } paramsChecker.myUsedTypeParams.add(typeParam); expression.accept( new JavaRecursiveElementWalkingVisitor() { @Override public void visitConditionalExpression(PsiConditionalExpression expression) { final PsiExpression thenExpression = expression.getThenExpression(); if (thenExpression != null) { thenExpression.accept(this); } final PsiExpression elseExpression = expression.getElseExpression(); if (elseExpression != null) { elseExpression.accept(this); } } @Override public void visitReferenceExpression(PsiReferenceExpression expression) { super.visitReferenceExpression(expression); int usedParamIdx = -1; for (int i = 0; i < lambdaParams.length; i++) { PsiParameter param = lambdaParams[i]; if (expression.isReferenceTo(param)) { usedParamIdx = i; break; } } if (usedParamIdx > -1 && dependsOnTypeParams( subst.substitute(methodParameters[usedParamIdx].getType()), functionalInterfaceType, lambdaExpression, paramsChecker.myUsedTypeParams.toArray( new PsiTypeParameter[paramsChecker.myUsedTypeParams.size()]))) { independent[0] = false; } } }); return independent[0]; }