@Nullable private ProblemDescriptor[] checkMember( final PsiDocCommentOwner docCommentOwner, final InspectionManager manager, final boolean isOnTheFly) { final ArrayList<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>(); final PsiDocComment docComment = docCommentOwner.getDocComment(); if (docComment == null) return null; final Set<PsiJavaCodeReferenceElement> references = new HashSet<PsiJavaCodeReferenceElement>(); docComment.accept(getVisitor(references, docCommentOwner, problems, manager, isOnTheFly)); for (PsiJavaCodeReferenceElement reference : references) { final List<PsiClass> classesToImport = new ImportClassFix(reference).getClassesToImport(); final PsiElement referenceNameElement = reference.getReferenceNameElement(); problems.add( manager.createProblemDescriptor( referenceNameElement != null ? referenceNameElement : reference, cannotResolveSymbolMessage("<code>" + reference.getText() + "</code>"), !isOnTheFly || classesToImport.isEmpty() ? null : new AddImportFix(classesToImport), ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, isOnTheFly)); } return problems.isEmpty() ? null : problems.toArray(new ProblemDescriptor[problems.size()]); }
private static void checkMethodReference( PsiMethodReferenceExpression expression, InspectionManager inspectionManager, List<ProblemDescriptor> problems) { final PsiTypeElement qualifierTypeElement = expression.getQualifierType(); if (qualifierTypeElement != null) { final PsiType psiType = qualifierTypeElement.getType(); if (psiType instanceof PsiClassType && !(((PsiClassType) psiType).isRaw())) { final JavaResolveResult result = expression.advancedResolve(false); final PsiElement element = result.getElement(); if (element instanceof PsiTypeParameterListOwner) { final PsiMethodReferenceExpression copy = createMethodReference(expression, qualifierTypeElement); final JavaResolveResult simplifiedResolve = copy.advancedResolve(false); final PsiElement candidate = simplifiedResolve.getElement(); if (candidate == element) { final PsiJavaCodeReferenceElement referenceElement = qualifierTypeElement.getInnermostComponentReferenceElement(); LOG.assertTrue(referenceElement != null, qualifierTypeElement); final PsiReferenceParameterList parameterList = referenceElement.getParameterList(); LOG.assertTrue(parameterList != null); final ProblemDescriptor descriptor = inspectionManager.createProblemDescriptor( parameterList, InspectionsBundle.message("inspection.redundant.type.problem.descriptor"), new MyMethodReferenceFixAction(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, false); problems.add(descriptor); } } } } }
public void applyFix( @NotNull final Project project, @NotNull final ProblemDescriptor descriptor) { final PsiElement element = PsiTreeUtil.getParentOfType( descriptor.getPsiElement(), PsiJavaCodeReferenceElement.class); if (element instanceof PsiJavaCodeReferenceElement) { final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement) element; Collections.sort( myClassesToImport, new PsiProximityComparator(referenceElement.getElement())); final JList list = new JBList(myClassesToImport.toArray(new PsiClass[myClassesToImport.size()])); list.setCellRenderer(new FQNameCellRenderer()); final Runnable runnable = new Runnable() { public void run() { if (!element.isValid()) return; final int index = list.getSelectedIndex(); if (index < 0) return; new WriteCommandAction(project, element.getContainingFile()) { protected void run(final Result result) throws Throwable { final PsiClass psiClass = myClassesToImport.get(index); if (psiClass.isValid()) { PsiDocumentManager.getInstance(project).commitAllDocuments(); referenceElement.bindToElement(psiClass); } } }.execute(); } }; final AsyncResult<DataContext> asyncResult = DataManager.getInstance().getDataContextFromFocus(); asyncResult.doWhenDone( new AsyncResult.Handler<DataContext>() { @Override public void run(DataContext dataContext) { final Editor editor = PlatformDataKeys.EDITOR.getData(dataContext); assert editor != null; // available for on the fly mode only new PopupChooserBuilder(list) .setTitle(QuickFixBundle.message("class.to.import.chooser.title")) .setItemChoosenCallback(runnable) .createPopup() .showInBestPositionFor(editor); } }); } }
private static PsiJavaCodeReferenceElement getQualifier(PsiElement qualifier) { if (qualifier instanceof PsiThisExpression) { final PsiJavaCodeReferenceElement thisQualifier = ((PsiThisExpression) qualifier).getQualifier(); if (thisQualifier != null) { final PsiClass innerMostClass = PsiTreeUtil.getParentOfType(thisQualifier, PsiClass.class); if (innerMostClass == thisQualifier.resolve()) { return null; } } return thisQualifier; } if (qualifier != null) { return ((PsiSuperExpression) qualifier).getQualifier(); } return null; }
private static boolean isInExtendsList( final RefJavaElement to, final PsiReferenceList extendsList) { if (extendsList != null) { final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements(); for (PsiJavaCodeReferenceElement referenceElement : referenceElements) { final PsiReferenceParameterList parameterList = referenceElement.getParameterList(); if (parameterList != null) { for (PsiType type : parameterList.getTypeArguments()) { if (extendsList .getManager() .areElementsEquivalent(PsiUtil.resolveClassInType(type), to.getElement())) { return true; } } } } } return false; }
/** * @return true if both expressions resolve to the same variable/class or field in the same * instance of the class */ private static boolean sameInstanceReferences( @Nullable PsiJavaCodeReferenceElement lRef, @Nullable PsiJavaCodeReferenceElement rRef, PsiManager manager) { if (lRef == null && rRef == null) return true; if (lRef == null || rRef == null) return false; PsiElement lResolved = lRef.resolve(); PsiElement rResolved = rRef.resolve(); if (!manager.areElementsEquivalent(lResolved, rResolved)) return false; if (!(lResolved instanceof PsiVariable)) return false; final PsiVariable variable = (PsiVariable) lResolved; if (variable.hasModifierProperty(PsiModifier.STATIC)) return true; final PsiElement lQualifier = lRef.getQualifier(); final PsiElement rQualifier = rRef.getQualifier(); if (lQualifier instanceof PsiJavaCodeReferenceElement && rQualifier instanceof PsiJavaCodeReferenceElement) { return sameInstanceReferences( (PsiJavaCodeReferenceElement) lQualifier, (PsiJavaCodeReferenceElement) rQualifier, manager); } if (Comparing.equal(lQualifier, rQualifier)) return true; boolean lThis = lQualifier == null || lQualifier instanceof PsiThisExpression || lQualifier instanceof PsiSuperExpression; boolean rThis = rQualifier == null || rQualifier instanceof PsiThisExpression || rQualifier instanceof PsiSuperExpression; if (lThis && rThis) { final PsiJavaCodeReferenceElement llQualifier = getQualifier(lQualifier); final PsiJavaCodeReferenceElement rrQualifier = getQualifier(rQualifier); return sameInstanceReferences(llQualifier, rrQualifier, manager); } return false; }
@Nullable public ProblemDescriptor[] checkFile( @NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) { // does not work in tests since CodeInsightTestCase copies file into temporary location if (ApplicationManager.getApplication().isUnitTestMode()) return null; if (file instanceof PsiJavaFile) { if (JspPsiUtil.isInJspFile(file)) return null; PsiJavaFile javaFile = (PsiJavaFile) file; PsiDirectory directory = javaFile.getContainingDirectory(); if (directory == null) return null; PsiPackage dirPackage = JavaDirectoryService.getInstance().getPackage(directory); if (dirPackage == null) return null; PsiPackageStatement packageStatement = javaFile.getPackageStatement(); // highlight the first class in the file only PsiClass[] classes = javaFile.getClasses(); if (classes.length == 0 && packageStatement == null) return null; String packageName = dirPackage.getQualifiedName(); if (!Comparing.strEqual(packageName, "", true) && packageStatement == null) { String description = JavaErrorMessages.message("missing.package.statement", packageName); return new ProblemDescriptor[] { manager.createProblemDescriptor( classes[0].getNameIdentifier(), description, new AdjustPackageNameFix(javaFile, null, dirPackage), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly) }; } if (packageStatement != null) { final PsiJavaCodeReferenceElement packageReference = packageStatement.getPackageReference(); PsiPackage classPackage = (PsiPackage) packageReference.resolve(); List<LocalQuickFix> availableFixes = new ArrayList<LocalQuickFix>(); if (classPackage == null) { availableFixes.add(new AdjustPackageNameFix(javaFile, packageStatement, dirPackage)); } else if (!Comparing.equal( dirPackage.getQualifiedName(), packageReference.getText(), true)) { availableFixes.add(new AdjustPackageNameFix(javaFile, packageStatement, dirPackage)); MoveToPackageFix moveToPackageFix = new MoveToPackageFix(file, classPackage); if (moveToPackageFix.isAvailable()) { availableFixes.add(moveToPackageFix); } } if (!availableFixes.isEmpty()) { String description = JavaErrorMessages.message( "package.name.file.path.mismatch", packageReference.getText(), dirPackage.getQualifiedName()); return new ProblemDescriptor[] { manager.createProblemDescriptor( packageStatement.getPackageReference(), description, isOnTheFly, availableFixes.toArray(new LocalQuickFix[availableFixes.size()]), ProblemHighlightType.GENERIC_ERROR_OR_WARNING) }; } } } return null; }