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 invoke( @NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); final int offset = TargetElementUtil.adjustOffset( file, editor.getDocument(), editor.getCaretModel().getOffset()); final PsiElement element = file.findElementAt(offset); PsiTypeElement typeElement = PsiTreeUtil.getParentOfType(element, PsiTypeElement.class); while (typeElement != null) { final PsiElement parent = typeElement.getParent(); PsiElement[] toMigrate = null; if (parent instanceof PsiVariable) { toMigrate = extractReferencedVariables(typeElement); } else if ((parent instanceof PsiMember && !(parent instanceof PsiClass)) || isClassArgument(parent)) { toMigrate = new PsiElement[] {parent}; } if (toMigrate != null && toMigrate.length > 0) { invoke(project, toMigrate, null, null, editor); return; } typeElement = PsiTreeUtil.getParentOfType(parent, PsiTypeElement.class, false); } CommonRefactoringUtil.showErrorHint( project, editor, "The caret should be positioned on type of field, variable, method or method parameter to be refactored", REFACTORING_NAME, "refactoring.migrateType"); }
private int substituteToTypeParameters( PsiTypeElement typeElement, PsiTypeElement inplaceTypeElement, PsiType[] paramVals, PsiTypeParameter[] params, TemplateBuilder builder, PsiSubstitutor rawingSubstitutor, boolean toplevel) { PsiType type = inplaceTypeElement.getType(); List<PsiType> types = new ArrayList<>(); for (int i = 0; i < paramVals.length; i++) { PsiType val = paramVals[i]; if (val == null) return SUBSTITUTED_NONE; if (type.equals(val)) { types.add(myFactory.createType(params[i])); } } if (!types.isEmpty()) { Project project = typeElement.getProject(); PsiType substituted = rawingSubstitutor.substitute(type); if (!CommonClassNames.JAVA_LANG_OBJECT.equals(substituted.getCanonicalText()) && (toplevel || substituted.equals(type))) { types.add(substituted); } builder.replaceElement( typeElement, new TypeExpression(project, types.toArray(PsiType.createArray(types.size())))); return toplevel ? SUBSTITUTED_IN_REF : SUBSTITUTED_IN_PARAMETERS; } boolean substituted = false; PsiJavaCodeReferenceElement ref = typeElement.getInnermostComponentReferenceElement(); PsiJavaCodeReferenceElement inplaceRef = inplaceTypeElement.getInnermostComponentReferenceElement(); if (ref != null) { LOG.assertTrue(inplaceRef != null); PsiTypeElement[] innerTypeElements = ref.getParameterList().getTypeParameterElements(); PsiTypeElement[] inplaceInnerTypeElements = inplaceRef.getParameterList().getTypeParameterElements(); for (int i = 0; i < innerTypeElements.length; i++) { substituted |= substituteToTypeParameters( innerTypeElements[i], inplaceInnerTypeElements[i], paramVals, params, builder, rawingSubstitutor, false) != SUBSTITUTED_NONE; } } return substituted ? SUBSTITUTED_IN_PARAMETERS : SUBSTITUTED_NONE; }
/** * Check the element. If the element is a PsiMethod, than we want to know if it's a @Provides * method, or a Constructor annotated w/ @Inject. * * <p>If element is a field, than we only want to see if it is annotated with @Inject. * * @return a {@link com.intellij.codeInsight.daemon.GutterIconNavigationHandler} for the * appropriate type, or null if we don't care about it. */ @Nullable @Override public LineMarkerInfo getLineMarkerInfo(@NotNull final PsiElement element) { // Check methods first (includes constructors). if (element instanceof PsiMethod) { PsiMethod methodElement = (PsiMethod) element; // @Provides if (PsiConsultantImpl.hasAnnotation(element, CLASS_PROVIDES)) { PsiTypeElement returnTypeElement = methodElement.getReturnTypeElement(); if (returnTypeElement != null) { return new LineMarkerInfo<PsiElement>( element, returnTypeElement.getTextRange(), ICON, UPDATE_ALL, null, new ProvidesToInjectHandler(), LEFT); } } // Constructor injection. if (methodElement.isConstructor() && PsiConsultantImpl.hasAnnotation(element, CLASS_INJECT)) { PsiIdentifier nameIdentifier = methodElement.getNameIdentifier(); if (nameIdentifier != null) { return new LineMarkerInfo<PsiElement>( element, nameIdentifier.getTextRange(), ICON, UPDATE_ALL, null, new ConstructorInjectToProvidesHandler(), LEFT); } } // Not a method, is it a Field? } else if (element instanceof PsiField) { // Field injection. PsiField fieldElement = (PsiField) element; PsiTypeElement typeElement = fieldElement.getTypeElement(); if (PsiConsultantImpl.hasAnnotation(element, CLASS_INJECT) && typeElement != null) { return new LineMarkerInfo<PsiElement>( element, typeElement.getTextRange(), ICON, UPDATE_ALL, null, new FieldInjectToProvidesHandler(), LEFT); } } return null; }
private static boolean typeElementsAreEquivalent( PsiTypeElement typeElement1, PsiTypeElement typeElement2) { if (typeElement1 == null) { return typeElement2 == null; } else if (typeElement2 == null) { return false; } final PsiType type1 = typeElement1.getType(); final PsiType type2 = typeElement2.getType(); return typesAreEquivalent(type1, type2); }
@Override protected void doFix(Project project, ProblemDescriptor descriptor) { final PsiElement element = descriptor.getPsiElement(); if (!(element instanceof PsiTypeElement)) { return; } final PsiTypeElement typeElement = (PsiTypeElement) element; final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); final PsiClassType type = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION); final PsiTypeElement newTypeElement = factory.createTypeElement(type); typeElement.replace(newTypeElement); }
@Nullable public static List<String> findTestDataFiles(@NotNull DataContext context) { final PsiMethod method = findTargetMethod(context); if (method == null) { return null; } final String name = method.getName(); if (name.startsWith("test")) { String testDataPath = TestDataLineMarkerProvider.getTestDataBasePath(method.getContainingClass()); final TestDataReferenceCollector collector = new TestDataReferenceCollector(testDataPath, name.substring(4)); return collector.collectTestDataReferences(method); } final Location<?> location = Location.DATA_KEY.getData(context); if (location instanceof PsiMemberParameterizedLocation) { PsiClass containingClass = ((PsiMemberParameterizedLocation) location).getContainingClass(); if (containingClass == null) { containingClass = PsiTreeUtil.getParentOfType(location.getPsiElement(), PsiClass.class, false); } if (containingClass != null) { final PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy( containingClass, Collections.singleton(JUnitUtil.RUN_WITH)); if (annotation != null) { final PsiAnnotationMemberValue memberValue = annotation.findAttributeValue("value"); if (memberValue instanceof PsiClassObjectAccessExpression) { final PsiTypeElement operand = ((PsiClassObjectAccessExpression) memberValue).getOperand(); if (operand.getType().equalsToText(Parameterized.class.getName())) { final String testDataPath = TestDataLineMarkerProvider.getTestDataBasePath(containingClass); final String paramSetName = ((PsiMemberParameterizedLocation) location).getParamSetName(); final String baseFileName = StringUtil.trimEnd(StringUtil.trimStart(paramSetName, "["), "]"); final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(containingClass.getProject()).getFileIndex(); return TestDataGuessByExistingFilesUtil.suggestTestDataFiles( fileIndex, baseFileName, testDataPath, containingClass); } } } } } return null; }
@Override protected final void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { final PsiElement element = descriptor.getPsiElement(); final PsiTypeElement castTypeElement; final PsiReferenceExpression reference; if (element instanceof PsiTypeCastExpression) { final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression) element; castTypeElement = typeCastExpression.getCastType(); final PsiExpression operand = typeCastExpression.getOperand(); if (!(operand instanceof PsiReferenceExpression)) { return; } reference = (PsiReferenceExpression) operand; } else if (element instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) element; final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (!(qualifier instanceof PsiClassObjectAccessExpression)) { return; } final PsiClassObjectAccessExpression classObjectAccessExpression = (PsiClassObjectAccessExpression) qualifier; castTypeElement = classObjectAccessExpression.getOperand(); final PsiExpressionList argumentList = methodCallExpression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); if (arguments.length != 1) { return; } final PsiExpression argument = arguments[0]; if (!(argument instanceof PsiReferenceExpression)) { return; } reference = (PsiReferenceExpression) argument; } else { return; } if (castTypeElement == null) { return; } final PsiInstanceOfExpression conflictingInstanceof = InstanceOfUtils.getConflictingInstanceof(castTypeElement.getType(), reference, element); final PsiTypeElement instanceofTypeElement = conflictingInstanceof.getCheckType(); if (instanceofTypeElement == null) { return; } final PsiElement newElement = replace(castTypeElement, instanceofTypeElement); final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); codeStyleManager.shortenClassReferences(newElement); }
@Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final String methodName = methodExpression.getReferenceName(); if (!"cast".equals(methodName)) { return; } final PsiMethod method = expression.resolveMethod(); if (method == null) { return; } final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) { return; } final String qualifiedName = containingClass.getQualifiedName(); if (!"java.lang.Class".equals(qualifiedName)) { return; } final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (!(qualifier instanceof PsiClassObjectAccessExpression)) { return; } final PsiClassObjectAccessExpression classObjectAccessExpression = (PsiClassObjectAccessExpression) qualifier; final PsiTypeElement operand = classObjectAccessExpression.getOperand(); final PsiType castType = operand.getType(); if (!(castType instanceof PsiClassType)) { return; } final PsiExpressionList argumentList = expression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); if (arguments.length != 1) { return; } final PsiExpression argument = arguments[0]; if (!(argument instanceof PsiReferenceExpression)) { return; } final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) argument; final PsiInstanceOfExpression conflictingInstanceof = InstanceOfUtils.getConflictingInstanceof(castType, referenceExpression, expression); if (conflictingInstanceof == null) { return; } final PsiTypeElement instanceofTypeElement = conflictingInstanceof.getCheckType(); registerError(expression, referenceExpression, operand, instanceofTypeElement); }
public static PsiClass getProviderClass(final PsiElement element, final PsiClass topLevelClass) { final PsiAnnotation annotation = PsiTreeUtil.getParentOfType(element, PsiAnnotation.class); if (annotation != null) { final PsiAnnotationMemberValue value = annotation.findDeclaredAttributeValue("dataProviderClass"); if (value instanceof PsiClassObjectAccessExpression) { final PsiTypeElement operand = ((PsiClassObjectAccessExpression) value).getOperand(); final PsiClass psiClass = PsiUtil.resolveClassInType(operand.getType()); if (psiClass != null) { return psiClass; } } } return topLevelClass; }
@NotNull private static PsiElement[] extractReferencedVariables(@NotNull PsiTypeElement typeElement) { final PsiElement parent = typeElement.getParent(); if (parent instanceof PsiVariable) { if (parent instanceof PsiField) { PsiField aField = (PsiField) parent; List<PsiField> fields = new ArrayList<>(); while (true) { fields.add(aField); aField = PsiTreeUtil.getNextSiblingOfType(aField, PsiField.class); if (aField == null || aField.getTypeElement() != typeElement) { return fields.toArray(new PsiElement[fields.size()]); } } } else if (parent instanceof PsiLocalVariable) { final PsiDeclarationStatement declaration = PsiTreeUtil.getParentOfType(parent, PsiDeclarationStatement.class); if (declaration != null) { return Arrays.stream(declaration.getDeclaredElements()) .filter(PsiVariable.class::isInstance) .toArray(PsiVariable[]::new); } } return new PsiElement[] {parent}; } else { return PsiElement.EMPTY_ARRAY; } }
@Nullable protected PsiType inferType(PsiTypeElement typeElement) { if (null == typeElement || DumbService.isDumb(typeElement.getProject())) { return null; } return valProcessor.inferType(typeElement); }
@NotNull @Override protected String buildErrorString(Object... infos) { final PsiTypeElement typeElement = (PsiTypeElement) infos[0]; final PsiElement parent = typeElement.getParent(); if (parent instanceof PsiField) { final PsiField field = (PsiField) parent; return InspectionGadgetsBundle.message( "optional.used.as.field.type.problem.descriptor", field.getName()); } else if (parent instanceof PsiParameter) { final PsiParameter parameter = (PsiParameter) parent; return InspectionGadgetsBundle.message( "optional.used.as.parameter.type.problem.descriptor", parameter.getName()); } throw new AssertionError(); }
private static PsiMethodReferenceExpression createMethodReference( PsiMethodReferenceExpression expression, PsiTypeElement typeElement) { final PsiType type = typeElement.getType(); final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(expression.getProject()); final PsiMethodReferenceExpression copy = (PsiMethodReferenceExpression) expression.copy(); copy.getQualifierType() .replace(elementFactory.createTypeElement(((PsiClassType) type).rawType())); return copy; }
private static boolean instanceofExpressionsAreEquivalent( PsiInstanceOfExpression instanceOfExpression1, PsiInstanceOfExpression instanceOfExpression2) { final PsiExpression operand1 = instanceOfExpression1.getOperand(); final PsiExpression operand2 = instanceOfExpression2.getOperand(); if (!expressionsAreEquivalent(operand1, operand2)) { return false; } final PsiTypeElement typeElement1 = instanceOfExpression1.getCheckType(); final PsiTypeElement typeElement2 = instanceOfExpression2.getCheckType(); if (typeElement1 == null) { return typeElement2 == null; } else if (typeElement2 == null) { return false; } final PsiType type1 = typeElement1.getType(); final PsiType type2 = typeElement2.getType(); return typesAreEquivalent(type1, type2); }
private static boolean typecastExpressionsAreEquivalent( @NotNull PsiTypeCastExpression typecastExp1, @NotNull PsiTypeCastExpression typecastExp2) { final PsiTypeElement typeElement1 = typecastExp1.getCastType(); final PsiTypeElement typeElement2 = typecastExp2.getCastType(); if (typeElement1 == null && typeElement2 == null) { return true; } if (typeElement1 == null || typeElement2 == null) { return false; } final PsiType type1 = typeElement1.getType(); final PsiType type2 = typeElement2.getType(); if (!typesAreEquivalent(type1, type2)) { return false; } final PsiExpression operand1 = typecastExp1.getOperand(); final PsiExpression operand2 = typecastExp2.getOperand(); return expressionsAreEquivalent(operand1, operand2); }
@Nullable public static HighlightInfo checkValidAnnotationType(final PsiTypeElement typeElement) { PsiType type = typeElement.getType(); if (type.accept(AnnotationReturnTypeVisitor.INSTANCE).booleanValue()) { return null; } String description = JavaErrorMessages.message("annotation.invalid.annotation.member.type"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(typeElement) .descriptionAndTooltip(description) .create(); }
@Override public void visitReferenceParameterList(PsiReferenceParameterList referenceParameterList) { super.visitReferenceParameterList(referenceParameterList); final PsiTypeElement[] typeParameterElements = referenceParameterList.getTypeParameterElements(); if (typeParameterElements.length == 1) { final PsiTypeElement typeParameterElement = typeParameterElements[0]; final PsiType type = typeParameterElement.getType(); if (type instanceof PsiDiamondType) { final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(referenceParameterList, PsiNewExpression.class); if (newExpression != null) { final List<PsiType> types = PsiDiamondTypeImpl.resolveInferredTypesNoCheck(newExpression, newExpression) .getInferredTypes(); if (!types.isEmpty()) { registerError(referenceParameterList); } } } } }
public static boolean isVal(@NotNull PsiTypeElement psiTypeElement) { final PsiJavaCodeReferenceElement referenceElement = psiTypeElement.getInnermostComponentReferenceElement(); if (null != referenceElement) { final PsiElement psiElement = referenceElement.resolve(); if (psiElement instanceof PsiClass) { final PsiClass psiClass = (PsiClass) psiElement; return isSameName(psiClass.getName()) && isSameName(psiClass.getQualifiedName()); } } return false; }
@Nullable public PsiType inferType(PsiTypeElement typeElement) { PsiType psiType = null; final PsiElement parent = typeElement.getParent(); if ((parent instanceof PsiLocalVariable || parent instanceof PsiParameter) && isVal(typeElement)) { if (parent instanceof PsiLocalVariable) { psiType = processLocalVariableInitializer(((PsiLocalVariable) parent).getInitializer()); } else { psiType = processParameterDeclaration(((PsiParameter) parent).getDeclarationScope()); } if (null == psiType) { psiType = PsiType.getJavaLangObject( typeElement.getManager(), GlobalSearchScope.projectScope(typeElement.getProject())); } } return psiType; }
@Nullable public static HighlightInfo checkCyclicMemberType(PsiTypeElement typeElement, PsiClass aClass) { LOG.assertTrue(aClass.isAnnotationType()); PsiType type = typeElement.getType(); final Set<PsiClass> checked = new HashSet<PsiClass>(); if (cyclicDependencies(aClass, type, checked, aClass.getManager())) { String description = JavaErrorMessages.message("annotation.cyclic.element.type"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(typeElement) .descriptionAndTooltip(description) .create(); } return null; }
@Override public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) { super.visitTypeCastExpression(expression); final PsiTypeElement castType = expression.getCastType(); if (castType == null) { return; } final PsiType type = castType.getType(); final PsiExpression operand = expression.getOperand(); if (!(operand instanceof PsiReferenceExpression)) { return; } final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) operand; final PsiInstanceOfExpression conflictingInstanceof = InstanceOfUtils.getConflictingInstanceof(type, referenceExpression, expression); if (conflictingInstanceof == null) { return; } final PsiTypeElement instanceofTypeElement = conflictingInstanceof.getCheckType(); if (instanceofTypeElement == null) { return; } registerError(expression, referenceExpression, castType, instanceofTypeElement); }
public void verifyTypeElement( @NotNull final PsiTypeElement psiTypeElement, @NotNull final ProblemsHolder holder) { final PsiElement typeParent = psiTypeElement.getParent(); if (isVal(psiTypeElement)) { if (typeParent instanceof PsiField || (typeParent instanceof PsiParameter && !(((PsiParameter) typeParent).getDeclarationScope() instanceof PsiForeachStatement))) { holder.registerProblem( psiTypeElement, "'val' works only on local variables and on foreach loops", ProblemHighlightType.ERROR); } else if (typeParent instanceof PsiLocalVariable) { final PsiLocalVariable psiVariable = (PsiLocalVariable) typeParent; final PsiExpression initializer = psiVariable.getInitializer(); if (initializer == null) { holder.registerProblem( psiTypeElement, "'val' on a local variable requires an initializer expression", ProblemHighlightType.ERROR); } else if (initializer instanceof PsiArrayInitializerExpression) { holder.registerProblem( psiTypeElement, "'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })", ProblemHighlightType.ERROR); } else if (initializer instanceof PsiLambdaExpression) { holder.registerProblem( psiTypeElement, "'val' is not allowed with lambda expressions.", ProblemHighlightType.ERROR); } else { final PsiElement typeParentParent = typeParent.getParent(); if (typeParentParent instanceof PsiDeclarationStatement && typeParentParent.getParent() instanceof PsiForStatement) { holder.registerProblem( psiTypeElement, "'val' is not allowed in old-style for loops", ProblemHighlightType.ERROR); } } } } }
private static void processPrimaryMethod( JavaChangeInfo changeInfo, PsiMethod method, PsiMethod baseMethod, boolean isOriginal) throws IncorrectOperationException { PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); if (changeInfo.isVisibilityChanged()) { PsiModifierList modifierList = method.getModifierList(); final String highestVisibility = isOriginal ? changeInfo.getNewVisibility() : VisibilityUtil.getHighestVisibility( changeInfo.getNewVisibility(), VisibilityUtil.getVisibilityModifier(modifierList)); VisibilityUtil.setVisibility(modifierList, highestVisibility); } if (changeInfo.isNameChanged()) { String newName = baseMethod == null ? changeInfo.getNewName() : RefactoringUtil.suggestNewOverriderName( method.getName(), baseMethod.getName(), changeInfo.getNewName()); if (newName != null && !newName.equals(method.getName())) { final PsiIdentifier nameId = method.getNameIdentifier(); assert nameId != null; nameId.replace( JavaPsiFacade.getInstance(method.getProject()) .getElementFactory() .createIdentifier(newName)); } } final PsiSubstitutor substitutor = baseMethod == null ? PsiSubstitutor.EMPTY : ChangeSignatureProcessor.calculateSubstitutor(method, baseMethod); if (changeInfo.isReturnTypeChanged()) { PsiType newTypeElement = changeInfo .getNewReturnType() .getType(changeInfo.getMethod().getParameterList(), method.getManager()); final PsiType returnType = substitutor.substitute(newTypeElement); // don't modify return type for non-Java overriders (EJB) if (method.getName().equals(changeInfo.getNewName())) { final PsiTypeElement typeElement = method.getReturnTypeElement(); if (typeElement != null) { typeElement.replace(factory.createTypeElement(returnType)); } } } PsiParameterList list = method.getParameterList(); PsiParameter[] parameters = list.getParameters(); final JavaParameterInfo[] parameterInfos = changeInfo.getNewParameters(); final int delta = baseMethod != null ? baseMethod.getParameterList().getParametersCount() - method.getParameterList().getParametersCount() : 0; PsiParameter[] newParms = new PsiParameter[Math.max(parameterInfos.length - delta, 0)]; final String[] oldParameterNames = changeInfo.getOldParameterNames(); final String[] oldParameterTypes = changeInfo.getOldParameterTypes(); for (int i = 0; i < newParms.length; i++) { JavaParameterInfo info = parameterInfos[i]; int index = info.getOldIndex(); if (index >= 0) { PsiParameter parameter = parameters[index]; newParms[i] = parameter; String oldName = oldParameterNames[index]; if (!oldName.equals(info.getName()) && oldName.equals(parameter.getName())) { PsiIdentifier newIdentifier = factory.createIdentifier(info.getName()); parameter.getNameIdentifier().replace(newIdentifier); } String oldType = oldParameterTypes[index]; if (!oldType.equals(info.getTypeText())) { parameter.normalizeDeclaration(); PsiType newType = substitutor.substitute( info.createType(changeInfo.getMethod().getParameterList(), method.getManager())); parameter.getTypeElement().replace(factory.createTypeElement(newType)); } } else { newParms[i] = createNewParameter(changeInfo, info, substitutor); } } resolveParameterVsFieldsConflicts(newParms, method, list, changeInfo.toRemoveParm()); fixJavadocsForChangedMethod(method, changeInfo, newParms.length); if (changeInfo.isExceptionSetOrOrderChanged()) { final PsiClassType[] newExceptions = getPrimaryChangedExceptionInfo(changeInfo); fixPrimaryThrowsLists(method, newExceptions); } }
@Override public ASTNode process( @NotNull ASTNode element, boolean addImports, boolean incompleteCode, boolean useFqInJavadoc, boolean useFqInCode) { IElementType elementType = element.getElementType(); if ((elementType == JavaElementType.JAVA_CODE_REFERENCE || elementType == JavaElementType.REFERENCE_EXPRESSION) && !isAnnotated(element)) { IElementType parentType = element.getTreeParent().getElementType(); if (elementType == JavaElementType.JAVA_CODE_REFERENCE || incompleteCode || parentType == JavaElementType.REFERENCE_EXPRESSION || parentType == JavaElementType.METHOD_REF_EXPRESSION) { PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement) element.getPsi(); PsiReferenceParameterList parameterList = ref.getParameterList(); if (parameterList != null) { PsiTypeElement[] typeParameters = parameterList.getTypeParameterElements(); for (PsiTypeElement typeParameter : typeParameters) { process( typeParameter.getNode(), addImports, incompleteCode, useFqInJavadoc, useFqInCode); } } boolean rightKind = true; if (elementType == JavaElementType.JAVA_CODE_REFERENCE) { PsiJavaCodeReferenceElementImpl impl = (PsiJavaCodeReferenceElementImpl) element; int kind = impl.getKind(impl.getContainingFile()); rightKind = kind == PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND || kind == PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND; } if (rightKind) { // annotations may jump out of reference (see PsiJavaCodeReferenceImpl#setAnnotations()) // so they should be processed first List<PsiAnnotation> annotations = PsiTreeUtil.getChildrenOfTypeAsList(ref, PsiAnnotation.class); for (PsiAnnotation annotation : annotations) { process(annotation.getNode(), addImports, incompleteCode, useFqInJavadoc, useFqInCode); } boolean isInsideDocComment = TreeUtil.findParent(element, JavaDocElementType.DOC_COMMENT) != null; boolean isShort = !ref.isQualified(); if (isInsideDocComment ? !useFqInJavadoc : !useFqInCode) { if (isShort) return element; // short name already, no need to change } PsiElement refElement; if (!incompleteCode) { refElement = ref.resolve(); } else { PsiResolveHelper helper = JavaPsiFacade.getInstance(ref.getManager().getProject()).getResolveHelper(); final SourceJavaCodeReference reference = (SourceJavaCodeReference) element; refElement = helper.resolveReferencedClass(reference.getClassNameText(), ref); } if (refElement instanceof PsiClass) { PsiClass psiClass = (PsiClass) refElement; if (isInsideDocComment ? useFqInJavadoc : useFqInCode) { String qName = psiClass.getQualifiedName(); if (qName == null) return element; PsiFile file = ref.getContainingFile(); if (file instanceof PsiJavaFile) { if (ImportHelper.isImplicitlyImported(qName, (PsiJavaFile) file)) { if (isShort) return element; return makeShortReference((CompositeElement) element, psiClass, addImports); } String thisPackageName = ((PsiJavaFile) file).getPackageName(); if (ImportHelper.hasPackage(qName, thisPackageName)) { if (!isShort) { return makeShortReference((CompositeElement) element, psiClass, addImports); } } } return replaceReferenceWithFQ(element, psiClass); } else { int oldLength = element.getTextLength(); ASTNode treeElement = makeShortReference((CompositeElement) element, psiClass, addImports); if (treeElement.getTextLength() == oldLength && psiClass.getContainingClass() != null) { PsiElement qualifier = ref.getQualifier(); if (qualifier instanceof PsiJavaCodeReferenceElement && ((PsiJavaCodeReferenceElement) qualifier).resolve() instanceof PsiClass) { process( qualifier.getNode(), addImports, incompleteCode, useFqInJavadoc, useFqInCode); } } return treeElement; } } } } } for (ASTNode child = element.getFirstChildNode(); child != null; child = child.getTreeNext()) { //noinspection AssignmentToForLoopParameter child = process(child, addImports, incompleteCode, useFqInJavadoc, useFqInCode); } return element; }
private void checkTypeElement(PsiTypeElement typeElement) { if (typeElement == null || !TypeUtils.isOptional(typeElement.getType())) { return; } registerError(typeElement, typeElement); }
@Override public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) { if (!MinecraftSettings.Companion.getInstance().isShowEventListenerGutterIcons()) { return; } // Since we want to line up with the method declaration, not the annotation // declaration, we need to target identifiers, not just PsiMethods. if (!(element instanceof PsiIdentifier && (element.getParent() instanceof PsiMethod))) { return; } // The PsiIdentifier is going to be a method of course! PsiMethod method = (PsiMethod) element.getParent(); if (method.hasModifierProperty(PsiModifier.ABSTRACT)) { // I don't think any implementation allows for abstract return; } PsiModifierList modifierList = method.getModifierList(); Module module = ModuleUtilCore.findModuleForPsiElement(element); if (module == null) { return; } MinecraftModule instance = MinecraftModule.getInstance(module); if (instance == null) { return; } // Since each platform has their own valid listener annotations, // some platforms may have multiple allowed annotations for various cases final Collection<AbstractModuleType<?>> moduleTypes = instance.getTypes(); boolean contains = false; for (AbstractModuleType<?> moduleType : moduleTypes) { final List<String> listenerAnnotations = moduleType.getListenerAnnotations(); for (String listenerAnnotation : listenerAnnotations) { if (modifierList.findAnnotation(listenerAnnotation) != null) { contains = true; break; } } } if (!contains) { return; } final PsiParameter[] parameters = method.getParameterList().getParameters(); if (parameters.length < 1) { return; } final PsiParameter eventParameter = parameters[0]; if (eventParameter == null) { // Listeners must have at least a single parameter return; } // Get the type of the parameter so we can start resolving it PsiTypeElement psiEventElement = eventParameter.getTypeElement(); if (psiEventElement == null) { return; } final PsiType type = psiEventElement.getType(); // Validate that it is a class reference type, I don't know if this will work with // other JVM languages such as Kotlin or Scala, but it might! if (!(type instanceof PsiClassReferenceType)) { return; } // And again, make sure that we can at least resolve the type, otherwise it's not a valid // class reference. final PsiClass eventClass = ((PsiClassReferenceType) type).resolve(); if (eventClass == null) { return; } if (instance.isEventClassValid(eventClass, method)) { return; } if (!instance.isStaticListenerSupported(eventClass, method) && method.hasModifierProperty(PsiModifier.STATIC)) { if (method.getNameIdentifier() != null) { holder.createErrorAnnotation( method.getNameIdentifier(), "Event listener method must not be static"); } } if (!isSuperEventListenerAllowed(eventClass, method, instance)) { holder.createErrorAnnotation( eventParameter, instance.writeErrorMessageForEvent(eventClass, method)); } }
@Nullable public static HighlightInfo checkApplicability( @NotNull PsiAnnotation annotation, @NotNull LanguageLevel languageLevel, @NotNull PsiFile containingFile) { if (ANY_ANNOTATION_ALLOWED.accepts(annotation)) { return null; } PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement(); if (nameRef == null) return null; PsiAnnotationOwner owner = annotation.getOwner(); PsiAnnotation.TargetType[] targets = PsiImplUtil.getTargetsForLocation(owner); if (owner == null || targets.length == 0) { String message = JavaErrorMessages.message("annotation.not.allowed.here"); return annotationError(annotation, message); } if (!(owner instanceof PsiModifierList)) { HighlightInfo info = HighlightUtil.checkTypeAnnotationFeature(annotation, languageLevel, containingFile); if (info != null) return info; } PsiAnnotation.TargetType applicable = PsiImplUtil.findApplicableTarget(annotation, targets); if (applicable == PsiAnnotation.TargetType.UNKNOWN) return null; if (applicable == null) { String target = JavaErrorMessages.message("annotation.target." + targets[0]); String message = JavaErrorMessages.message("annotation.not.applicable", nameRef.getText(), target); return annotationError(annotation, message); } if (applicable == PsiAnnotation.TargetType.TYPE_USE) { if (owner instanceof PsiClassReferenceType) { PsiJavaCodeReferenceElement ref = ((PsiClassReferenceType) owner).getReference(); HighlightInfo info = checkReferenceTarget(annotation, ref); if (info != null) return info; } else if (owner instanceof PsiModifierList) { PsiElement nextElement = PsiTreeUtil.skipSiblingsForward( (PsiModifierList) owner, PsiComment.class, PsiWhiteSpace.class, PsiTypeParameterList.class); if (nextElement instanceof PsiTypeElement) { PsiTypeElement typeElement = (PsiTypeElement) nextElement; PsiType type = typeElement.getType(); if (PsiType.VOID.equals(type)) { String message = JavaErrorMessages.message("annotation.not.allowed.void"); return annotationError(annotation, message); } if (!(type instanceof PsiPrimitiveType)) { PsiJavaCodeReferenceElement ref = getOutermostReferenceElement(typeElement.getInnermostComponentReferenceElement()); HighlightInfo info = checkReferenceTarget(annotation, ref); if (info != null) return info; } } } else if (owner instanceof PsiTypeElement) { PsiElement context = PsiTreeUtil.skipParentsOfType((PsiTypeElement) owner, PsiTypeElement.class); if (context instanceof PsiClassObjectAccessExpression) { String message = JavaErrorMessages.message("annotation.not.allowed.class"); return annotationError(annotation, message); } } } return null; }
@Override public void beforeCompletion(@NotNull final CompletionInitializationContext context) { final PsiFile file = context.getFile(); if (file instanceof PsiJavaFile) { if (context.getInvocationCount() > 0) { autoImport(file, context.getStartOffset() - 1, context.getEditor()); PsiElement leaf = file.findElementAt(context.getStartOffset() - 1); if (leaf != null) leaf = PsiTreeUtil.prevVisibleLeaf(leaf); PsiVariable variable = PsiTreeUtil.getParentOfType(leaf, PsiVariable.class); if (variable != null) { PsiTypeElement typeElement = variable.getTypeElement(); if (typeElement != null) { PsiType type = typeElement.getType(); if (type instanceof PsiClassType && ((PsiClassType) type).resolve() == null) { autoImportReference( file, context.getEditor(), typeElement.getInnermostComponentReferenceElement()); } } } } JavaCompletionUtil.initOffsets(file, context.getOffsetMap()); 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 static boolean textMatches(@Nullable PsiTypeElement typeElement, @NotNull String text) { return typeElement != null && typeElement.textMatches(text); }