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; }
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 static String checkTypeArguments(PsiTypeElement qualifier, PsiType psiType) { if (psiType instanceof PsiClassType) { final PsiJavaCodeReferenceElement referenceElement = qualifier.getInnermostComponentReferenceElement(); if (referenceElement != null) { PsiType[] typeParameters = referenceElement.getTypeParameters(); for (PsiType typeParameter : typeParameters) { if (typeParameter instanceof PsiWildcardType) { return "Unexpected wildcard"; } } } } return null; }
@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); } } }
public void setupTypeElement( PsiTypeElement typeElement, ExpectedTypeInfo[] infos, PsiSubstitutor substitutor, TemplateBuilder builder, @Nullable PsiElement context, PsiClass targetClass) { LOG.assertTrue(typeElement.isValid()); ApplicationManager.getApplication().assertWriteAccessAllowed(); PsiManager manager = typeElement.getManager(); GlobalSearchScope scope = typeElement.getResolveScope(); Project project = manager.getProject(); if (infos.length == 1 && substitutor != null && substitutor != PsiSubstitutor.EMPTY) { ExpectedTypeInfo info = infos[0]; Map<PsiTypeParameter, PsiType> map = substitutor.getSubstitutionMap(); PsiType[] vals = map.values().toArray(PsiType.createArray(map.size())); PsiTypeParameter[] params = map.keySet().toArray(new PsiTypeParameter[map.size()]); List<PsiType> types = matchingTypeParameters(vals, params, info); if (!types.isEmpty()) { ContainerUtil.addAll( types, ExpectedTypesProvider.processExpectedTypes( infos, new MyTypeVisitor(manager, scope), project)); builder.replaceElement( typeElement, new TypeExpression(project, types.toArray(PsiType.createArray(types.size())))); return; } else { PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); PsiType type = info.getType(); PsiType defaultType = info.getDefaultType(); try { PsiTypeElement inplaceTypeElement = ((PsiVariable) factory.createVariableDeclarationStatement("foo", type, null) .getDeclaredElements()[0]) .getTypeElement(); PsiSubstitutor rawingSubstitutor = getRawingSubstitutor(context, targetClass); int substitionResult = substituteToTypeParameters( typeElement, inplaceTypeElement, vals, params, builder, rawingSubstitutor, true); if (substitionResult != SUBSTITUTED_NONE) { if (substitionResult == SUBSTITUTED_IN_PARAMETERS) { PsiJavaCodeReferenceElement refElement = typeElement.getInnermostComponentReferenceElement(); LOG.assertTrue(refElement != null && refElement.getReferenceNameElement() != null); type = getComponentType(type); LOG.assertTrue(type != null); defaultType = getComponentType(defaultType); LOG.assertTrue(defaultType != null); ExpectedTypeInfo info1 = ExpectedTypesProvider.createInfo( ((PsiClassType) defaultType).rawType(), ExpectedTypeInfo.TYPE_STRICTLY, ((PsiClassType) defaultType).rawType(), info.getTailType()); MyTypeVisitor visitor = new MyTypeVisitor(manager, scope); builder.replaceElement( refElement.getReferenceNameElement(), new TypeExpression( project, ExpectedTypesProvider.processExpectedTypes( new ExpectedTypeInfo[] {info1}, visitor, project))); } return; } } catch (IncorrectOperationException e) { LOG.error(e); } } } PsiType[] types = infos.length == 0 ? new PsiType[] {typeElement.getType()} : ExpectedTypesProvider.processExpectedTypes( infos, new MyTypeVisitor(manager, scope), project); builder.replaceElement(typeElement, new TypeExpression(project, types)); }