@Nullable public static PsiType getWritablePropertyType(@Nullable PsiClass containingClass, @Nullable PsiElement declaration) { if (declaration instanceof PsiField) { return getWrappedPropertyType((PsiField) declaration, JavaFxCommonNames.ourWritableMap); } if (declaration instanceof PsiMethod) { final PsiMethod method = (PsiMethod) declaration; if (method.getParameterList().getParametersCount() != 0) { return getSetterArgumentType(method); } final String propertyName = PropertyUtil.getPropertyName(method); final PsiClass psiClass = containingClass != null ? containingClass : method.getContainingClass(); if (propertyName != null && containingClass != null) { final PsiMethod setter = findInstancePropertySetter(psiClass, propertyName); if (setter != null) { final PsiType setterArgumentType = getSetterArgumentType(setter); if (setterArgumentType != null) return setterArgumentType; } } return getGetterReturnType(method); } return null; }
@DataProvider public static Object[][] tooComplexProvider() { return testForEach( new TestCase().withTypeMock(mock(PsiClassType.class)) .withQualifiedNameOf(String.class).thenExpectTheResult().toBeTooGeneric(), new TestCase().withTypeMock(mock(PsiClassType.class)) .withQualifiedNameOf(Integer.class).thenExpectTheResult().toBeTooGeneric(), new TestCase().withTypeMock(mock(PsiClassType.class)) .withQualifiedNameOf(List.class).thenExpectTheResult().toBeTooGeneric(), new TestCase().withTypeMock(mock(PsiClassType.class)) .withQualifiedNameOf(Stream.class).thenExpectTheResult().toBeTooGeneric(), new TestCase().withTypeMock(mock(PsiClassType.class)) .withQualifiedNameOf(BufferedReader.class).thenExpectTheResult().toBeTooGeneric(), new TestCase().withTypeMock(mock(PsiType.class)) .withQualifiedName("some_qualified_name").thenExpectTheResult().toBeTooGeneric(), new TestCase().withTypeMock(mock(PsiClassType.class)) .withQualifiedName(null).thenExpectTheResult().toBeTooGeneric(), new TestCase().withTypeMock(mock(PsiClassType.class)) .withQualifiedName("myClass").thenExpectTheResult().toBeNotTooGeneric() ); }
private boolean checkMethodSignature(PsiMethod method) { // subscribe() calls that have no return type are custom Observers whose error handling we cannot check if (PsiType.VOID.equals(method.getReturnType())) { return false; } int argCount = method.getParameterList().getParametersCount(); // when more than one argument is given, there is usually one error callback included if (argCount > 1) { return false; } // no arguments, no error handling if (argCount == 0) { return true; } // if we have only one argument, check that it's not a BiConsumer PsiParameter parameter = method.getParameterList().getParameters()[0]; return !"io.reactivex.functions.BiConsumer".equals(parameter.getType().getCanonicalText()); }
@Override public void visitMethod(JavaContext context, JavaElementVisitor visitor, PsiMethodCallExpression call, PsiMethod method) { super.visitMethod(context, visitor, call, method); if (isRxSubscribeableClass(method.getContainingClass()) && !PsiType.VOID.equals(method.getReturnType())) { PsiElement element = LintUtils.skipParentheses(call.getParent()); if (element instanceof PsiExpressionStatement) { String message; if (isRx2(method.getContainingClass())) { message = "No reference to the disposable is kept"; } else { message = "No reference to the subscription is kept"; } context.report(ISSUE, call, context.getLocation(call), message); } } }
public static boolean isOfType(PsiType type, String canonicalName) { if (type.getCanonicalText().equals(canonicalName)) { return true; } final String nonGenericType = getNonGenericType(type); if (nonGenericType != null && nonGenericType.equals(canonicalName)) { return true; } for (PsiType iterType : type.getSuperTypes()) { if (isOfType(iterType, canonicalName)) { return true; } } return false; }
private Optional<ConfigInfo> extractConfigInfo(PropertiesFile propertiesFile, CoffigResolver.Match match) { Optional<String> description = Optional.ofNullable(propertiesFile.findPropertyByKey(match.getUnmatchedPath())).map(IProperty::getValue); if (description.isPresent()) { // Base info ConfigInfo configInfo = new ConfigInfo(match.getFullPath(), description.get()); // Extended info Optional.ofNullable(propertiesFile.findPropertyByKey(match.getUnmatchedPath() + ".long")).map(IProperty::getValue).ifPresent(configInfo::setLongDescription); // Field info CoffigResolver.Match resolvedMatch = match.fullyResolve(); if (resolvedMatch.isFullyResolved()) { Optional<PsiField> psiField = resolvedMatch.resolveField(resolvedMatch.getUnmatchedPath()); psiField.map(PsiVariable::getType).map(PsiType::getPresentableText).ifPresent(configInfo::setType); } return Optional.of(configInfo); } return Optional.empty(); }
void check(@NonNull PsiMethod method) { if (mClass != null && !mClassFields.isEmpty()) { // メソッド引数に boolean のパラメータがある場合のみ対象とする Map<String, PsiParameter> parameters = new HashMap<>(); PsiParameter[] params = method.getParameterList().getParameters(); for (PsiParameter param : params) { if (param.getType() != PsiType.BOOLEAN) continue; parameters.put(param.getName(), param); } if (parameters.isEmpty()) return; mMethod = method; mFlagMethodParameters.clear(); mFlagMethodParameters.putAll(parameters); mFlagLogic = null; } }
@Override public Stream<LookupElementBuilder> resolveCompletions(String propertyName, PsiType psiType) { PsiType[] parameters = ((PsiClassReferenceType) psiType).getParameters(); Stream<PsiClass> psiClassStream = null; if (parameters.length == 1 && parameters[0] instanceof PsiWildcardType) { PsiWildcardType psiWildcardType = ((PsiWildcardType) parameters[0]); if (psiWildcardType.isBounded()) { if (psiWildcardType.isExtends()) { psiClassStream = subClasses((PsiClassType) psiWildcardType.getExtendsBound()).stream(); } else if (psiWildcardType.isSuper()) { psiClassStream = superClasses((PsiClassType) psiWildcardType.getSuperBound()).stream(); } } } if (psiClassStream != null) { return psiClassStream.map(this::buildClassLookup).filter(Optional::isPresent).map(Optional::get); } else { return Stream.empty(); } }
Optional<PsiClass> resolveFieldConfigType(PsiField psiField) { PsiType fieldType = psiField.getType(); if (fieldType instanceof PsiClassType) { PsiClassType fieldClassType = ((PsiClassType) fieldType); if (collectionType != null && collectionType.isAssignableFrom(fieldType) && fieldClassType.getParameterCount() == 1) { return toPsiClass(fieldClassType.getParameters()[0]); } else if (mapType != null && mapType.isAssignableFrom(fieldType) && fieldClassType.getParameterCount() == 2) { return toPsiClass(fieldClassType.getParameters()[1]); } else { return toPsiClass(fieldType); } } else if (fieldType instanceof PsiArrayType) { return toPsiClass(((PsiArrayType) fieldType).getComponentType()); } else { return Optional.empty(); } }
private PsiElement findExtensionMethodNavigationElement( PsiClass extClass, PsiMethod plantedMethod ) { PsiMethod[] found = extClass.findMethodsByName( plantedMethod.getName(), false ); outer: for( PsiMethod m : found ) { PsiParameter[] extParams = m.getParameterList().getParameters(); PsiParameter[] plantedParams = plantedMethod.getParameterList().getParameters(); if( extParams.length - 1 == plantedParams.length ) { for( int i = 1; i < extParams.length; i++ ) { PsiParameter extParam = extParams[i]; PsiParameter plantedParam = plantedParams[i - 1]; PsiType extErased = TypeConversionUtil.erasure( extParam.getType() ); PsiType plantedErased = TypeConversionUtil.erasure( plantedParam.getType() ); if( !extErased.toString().equals( plantedErased.toString() ) ) { continue outer; } } return m.getNavigationElement(); } } return null; }
@Nullable public PsiType inferType( PsiTypeElement typeElement ) { PsiType psiType = null; final PsiElement parent = typeElement.getParent(); if( (parent instanceof PsiLocalVariable && isVar( (PsiLocalVariable)parent )) || (parent instanceof PsiParameter && isVarForEach( (PsiParameter)parent )) ) { if( parent instanceof PsiLocalVariable ) { psiType = processLocalVariableInitializer( ((PsiLocalVariable)parent).getInitializer() ); } else { psiType = processForeach( ((PsiParameter)parent).getDeclarationScope() ); } if( null == psiType ) { psiType = PsiType.getJavaLangObject( typeElement.getManager(), GlobalSearchScope.allScope( typeElement.getProject() ) ); } } return psiType; }
private SrcType makeSrcType( PsiType type ) { SrcType srcType; if( type instanceof PsiClassType ) { srcType = new SrcType( ((PsiClassType)type).rawType().getCanonicalText() ); for( PsiType typeParam : ((PsiClassType)type).getParameters() ) { srcType.addTypeParam( makeSrcType( typeParam ) ); } } else { srcType = new SrcType( type.getCanonicalText() ); } return srcType; }
private static boolean isAssignable( boolean structural, boolean covariant, PsiType to, PsiType from ) { if( to.equals( from ) ) { return true; } if( structural ) { return TypeConversionUtil.isAssignable( to, from ) || arePrimitiveTypesAssignable( to, from ) || isStructurallyAssignable( to, from, structural ) || TypeConversionUtil.boxingConversionApplicable( to, from ); } if( covariant ) { TypeConversionUtil.isAssignable( to, from ); } return false; }
private static PsiType findGreatestLowerBound( PsiType t1, PsiType t2 ) { if( t1.equals( t2 ) ) { return t1; } if( t1.isAssignableFrom( t2 ) ) { return t2; } if( t2.isAssignableFrom( t1 ) ) { return t1; } return t1; //## todo: return JavaTypes.VOID() or return null or Object? }
public static PsiType maybeInferParamType( TypeVarToTypeMap inferenceMap, PsiType ownersType, PsiType fromParamType, PsiType toParamType ) { int iCount = inferenceMap.size(); PsiType toCompType = toParamType; while( toCompType instanceof PsiArrayType ) { toCompType = ((PsiArrayType)toCompType).getComponentType(); } if( isTypeVariable( toCompType ) || isParameterizedType( toCompType ) ) { inferTypeVariableTypesFromGenParamTypeAndConcreteType_Reverse( toParamType, fromParamType, inferenceMap ); if( inferenceMap.size() > iCount ) { PsiType actualType = getActualType( toParamType, inferenceMap, false ); toParamType = actualType == null ? toParamType : actualType; } } return replaceTypeVariableTypeParametersWithBoundingTypes( toParamType, ownersType ); }
public static PsiType maybeInferReturnType( TypeVarToTypeMap inferenceMap, PsiType ownersType, PsiType fromReturnType, PsiType toReturnType ) { int iCount = inferenceMap.size(); PsiType toCompType = toReturnType; while( toCompType instanceof PsiArrayType ) { toCompType = ((PsiArrayType)toCompType).getComponentType(); } boolean bTypeVar = isTypeVariable( toCompType ); if( bTypeVar || isParameterizedType( toCompType ) ) { inferTypeVariableTypesFromGenParamTypeAndConcreteType( toReturnType, fromReturnType, inferenceMap ); if( bTypeVar && inferenceMap.get( (PsiClassType)toCompType ) != null || inferenceMap.size() > iCount ) { PsiType actualType = getActualType( toReturnType, inferenceMap, false ); toReturnType = actualType == null ? toReturnType : actualType; } } return replaceTypeVariableTypeParametersWithBoundingTypes( toReturnType, ownersType ); }
public static PsiType makeDefaultParameterizedType( PsiType type ) { if( type != null && !isStructuralInterface( type ) && !isParameterizedType( type ) && isGenericType( type ) ) { PsiTypeParameter[] typeVars = type( type ).getTypeParameters(); PsiType[] boundingTypes = new PsiType[typeVars.length]; for( int i = 0; i < boundingTypes.length; i++ ) { PsiTypeParameter typeVar = typeVars[i]; boundingTypes[i] = type( getBoundingType( typeVar ) ); if( isRecursiveType( (PsiClassType)type( typeVar ), boundingTypes[i] ) ) { return type; } } if( boundingTypes.length == 0 ) { return type; } type = parameterizeType( (PsiClassType)type, boundingTypes ); } return type; }
public static PsiType getDefaultParameterizedType( PsiType type, PsiManager mgr ) { if( type.getArrayDimensions() > 0 ) { PsiType defType = getDefaultParameterizedType( ((PsiArrayType)type).getComponentType(), mgr ); if( !defType.equals( type ) ) { return new PsiArrayType( defType ); } return type; } if( type instanceof PsiIntersectionType ) { return makeDefaultParameterizedTypeForCompoundType( (PsiIntersectionType)type, mgr ); } if( type instanceof PsiDisjunctionType ) { return getDefaultParameterizedType( PsiTypesUtil.getLowestUpperBoundClassType( (PsiDisjunctionType)type ), mgr ); } if( !isGenericType( type ) && !isParameterizedType( type ) ) { return type; } type = ((PsiClassType)type).rawType(); return makeDefaultParameterizedType( type ); }
private static PsiType makeDefaultParameterizedTypeForCompoundType( PsiIntersectionType type, PsiManager mgr ) { PsiType[] types = type.getConjuncts(); PsiType[] defCompTypes = new PsiType[types.length]; int i = 0; boolean bDifferent = false; for( PsiType compType : types ) { defCompTypes[i++] = getDefaultParameterizedType( compType, mgr ); bDifferent = bDifferent || !defCompTypes[i].equals( compType ); } if( bDifferent ) { return PsiIntersectionType.createIntersection( defCompTypes ); } return type; }
private static PsiType maybeGetLowerBound( PsiWildcardType type, TypeVarToTypeMap actualParamByVarName, boolean bKeepTypeVars, LinkedHashSet<PsiType> recursiveTypes ) { PsiType lower = type.getSuperBound(); if( lower != PsiType.NULL && recursiveTypes.size() > 0 ) { // This is a "super" (contravariant) wildcard LinkedList<PsiType> list = new LinkedList<>( recursiveTypes ); PsiType enclType = list.getLast(); if( isParameterizedType( enclType ) ) { PsiType genType = getActualType( ((PsiClassType)enclType).rawType(), actualParamByVarName, bKeepTypeVars, recursiveTypes ); if( LambdaUtil.isFunctionalType( genType ) ) { // For functional interfaces we keep the lower bound as an upper bound so that blocks maintain contravariance wrt the single method's parameters return lower; } } } return null; }
private static TypeVarToTypeMap mapActualTypeByVarName( PsiType ownersType ) { TypeVarToTypeMap actualParamByVarName = new TypeVarToTypeMap(); PsiTypeParameter[] vars = type( ownersType ).getTypeParameters(); if( vars != null ) { PsiType[] paramArgs = ((PsiClassType)ownersType).getParameters(); for( int i = 0; i < vars.length; i++ ) { PsiClassType typeVar = (PsiClassType)type( vars[i] ); if( paramArgs.length > i ) { actualParamByVarName.put( typeVar, paramArgs[i] ); } } } return actualParamByVarName; }
private static Class<?> getType(UExpression expression) { if (expression == null) { return null; } if (expression instanceof PsiMethodCallExpression) { PsiMethodCallExpression call = (PsiMethodCallExpression) expression; PsiMethod method = call.resolveMethod(); if (method == null) { return null; } String methodName = method.getName(); if (methodName.equals(GET_STRING_METHOD)) { return String.class; } } else if (expression instanceof PsiLiteralExpression) { PsiLiteralExpression literalExpression = (PsiLiteralExpression) expression; PsiType expressionType = literalExpression.getType(); if (LintUtils.isString(expressionType)) { return String.class; } else if (expressionType == PsiType.INT) { return Integer.TYPE; } else if (expressionType == PsiType.FLOAT) { return Float.TYPE; } else if (expressionType == PsiType.CHAR) { return Character.TYPE; } else if (expressionType == PsiType.BOOLEAN) { return Boolean.TYPE; } else if (expressionType == PsiType.NULL) { return Object.class; } } PsiType type = expression.getExpressionType(); if (type != null) { Class<?> typeClass = getTypeClass(type); return typeClass != null ? typeClass : Object.class; } return null; }
private static boolean isSubclassOf(JavaContext context, UExpression expression, Class<?> cls) { PsiType expressionType = expression.getExpressionType(); if (expressionType instanceof PsiClassType) { PsiClassType classType = (PsiClassType) expressionType; PsiClass resolvedClass = classType.resolve(); return context.getEvaluator().extendsClass(resolvedClass, cls.getName(), false); } return false; }
@Nullable public static PsiType getWrappedPropertyType(final PsiField field) { return CachedValuesManager.getCachedValue(field, () -> { final PsiType fieldType = field.getType(); final PsiClassType.ClassResolveResult resolveResult = com.intellij.psi.util.PsiUtil.resolveGenericsClassInType(fieldType); final PsiClass fieldClass = resolveResult.getElement(); if (fieldClass == null) { final PsiType propertyType = eraseFreeTypeParameters(fieldType, field); return CachedValueProvider.Result.create(propertyType, JAVA_STRUCTURE_MODIFICATION_COUNT); } return CachedValueProvider.Result.create(null, JAVA_STRUCTURE_MODIFICATION_COUNT); }); }
@Nullable private static PsiType getSetterArgumentType(@NotNull PsiMethod method) { return CachedValuesManager.getCachedValue(method, () -> { final PsiParameter[] parameters = method.getParameterList().getParameters(); if (!method.hasModifierProperty(STATIC) && parameters.length == 1) { final PsiType argumentType = eraseFreeTypeParameters(parameters[0].getType(), method); return CachedValueProvider.Result.create(argumentType, JAVA_STRUCTURE_MODIFICATION_COUNT); } return CachedValueProvider.Result.create(null, JAVA_STRUCTURE_MODIFICATION_COUNT); }); }
@Nullable private static PsiType eraseFreeTypeParameters(@Nullable PsiType psiType, @Nullable PsiClass containingClass) { if (containingClass == null) return null; return JavaPsiFacade.getElementFactory(containingClass.getProject()) .createRawSubstitutor(containingClass).substitute(psiType); }
public static PsiClassType findParameterizedType( PsiClassType sourceType, PsiClassType rawGenericType, boolean bForAssignability ) { if( sourceType == null ) { return null; } rawGenericType = rawGenericType.rawType(); final PsiType srcRawType = sourceType.rawType(); PsiClass sourcePsiClass = type( sourceType ); if( srcRawType.equals( rawGenericType ) || !bForAssignability && rawGenericType.equals( PsiType.getJavaLangClass( sourcePsiClass.getManager(), GlobalSearchScope.allScope( sourcePsiClass.getProject() ) ) ) ) { return sourceType; } PsiClassType parameterizedType = findParameterizedType( (PsiClassType)type( sourcePsiClass.getSuperClass() ), rawGenericType, bForAssignability ); if( parameterizedType != null ) { return parameterizedType; } PsiClass[] interfaces = sourceType.resolve().getInterfaces(); for( int i = 0; i < interfaces.length; i++ ) { PsiClass iface = interfaces[i]; parameterizedType = findParameterizedType( (PsiClassType)type( iface ), rawGenericType, bForAssignability ); if( parameterizedType != null ) { return parameterizedType; } } return null; }
public PsiType getByString( String tv ) { for( PsiClassType key: _map.keySet() ) { if( tv.equals( key.getCanonicalText() ) || tv.equals( key.getCanonicalText() ) ) { return key; } } return null; }
private void mockPsiClassWith(PsiType psiType, String qualifiedName) { if (psiType instanceof PsiClassType) { PsiClass clazz = mock(PsiClass.class); when(clazz.getQualifiedName()).thenReturn(qualifiedName); when(((PsiClassType) psiType).resolve()).thenReturn(clazz); } }
private boolean isFieldMissingNullAnnotation(PsiField field, PsiType type) { return reportFields && field.isPhysical() && !(field instanceof PsiEnumConstant) && !TypeConversionUtil.isPrimitiveAndNotNull(type) && shouldCheckField(field) && !hasAnnotation(field); }
@Nonnull @Override public String convert(@Nonnull String name, @Nonnull TypeName type) { final String variableName = DefaultNamePolicy.format(name, CaseFormat.UPPER_CAMEL); if (Strings.isNullOrEmpty(variableName)) { throw new IllegalArgumentException("Cannot convert '" + name + "' to a method name"); } try { final PsiType psiType = typeConverter.apply(type); return GenerateMembersUtil.suggestGetterName(variableName, psiType, project); } catch (IncorrectOperationException e) { throw new IllegalArgumentException("Cannot convert '" + name + "' to a method name", e); } }
@Nonnull @CheckReturnValue @Override public PsiType apply(@Nonnull TypeName typeName) { return Stream.of(PrimitiveType.values()) .filter(primitiveType -> primitiveType.isSameAs(typeName)) .map(PrimitiveType::psiType) .findFirst() .orElseGet(() -> PsiType.getJavaLangObject(psiManager, GlobalSearchScope.EMPTY_SCOPE)); }
@Parameters(name = "should return {1} when {0}") public static Collection<Object[]> fixtures() { return Arrays.asList(new Object[][]{ {TypeName.BOOLEAN, PsiType.BOOLEAN}, {TypeName.BYTE, PsiType.BYTE}, {TypeName.CHAR, PsiType.CHAR}, {TypeName.DOUBLE, PsiType.DOUBLE}, {TypeName.FLOAT, PsiType.FLOAT}, {TypeName.INT, PsiType.INT}, {TypeName.LONG, PsiType.LONG}, {TypeName.SHORT, PsiType.SHORT}, {TypeName.VOID, PsiType.VOID}, }); }
@Test public void apply() throws Exception { // exercise final PsiType actual = underTest.apply(typeName); // verify assertThat(actual) .isEqualTo(expected); }
/** * Checks that the given type is an implementer of the given canonicalName with the given typed parameters * * @param type what we're checking against * @param canonicalName the type must extend/implement this generic * @param canonicalParamNames the type that the generic(s) must be (in this order) * @return */ public static boolean isTypedClass(PsiType type, String canonicalName, String... canonicalParamNames) { PsiClass parameterClass = PsiTypesUtil.getPsiClass(type); if (parameterClass == null) { return false; } // This is a safe cast, for if parameterClass != null, the type was checked in PsiTypesUtil#getPsiClass(...) PsiClassType pct = (PsiClassType) type; // Main class name doesn't match; exit early if (!canonicalName.equals(parameterClass.getQualifiedName())) { return false; } List<PsiType> psiTypes = new ArrayList<PsiType>(pct.resolveGenerics().getSubstitutor().getSubstitutionMap().values()); for (int i = 0; i < canonicalParamNames.length; i++) { if (!isOfType(psiTypes.get(i), canonicalParamNames[i])) { return false; } } // Passed all screenings; must be a match! return true; }
/** * Resolves generics on the given type and returns them (if any) or null if there are none */ public static List<PsiType> getResolvedGenerics(PsiType type) { List<PsiType> psiTypes = null; if (type instanceof PsiClassType) { PsiClassType pct = (PsiClassType) type; psiTypes = new ArrayList<PsiType>(pct.resolveGenerics().getSubstitutor().getSubstitutionMap().values()); } return psiTypes; }
public static String getNonGenericType(PsiType type) { if (type instanceof PsiClassType) { PsiClassType pct = (PsiClassType) type; final PsiClass psiClass = pct.resolve(); return psiClass != null ? psiClass.getQualifiedName() : null; } return type.getCanonicalText(); }
@Override public boolean canHandle(PsiType psiType) { if (psiType instanceof PsiClassReferenceType) { PsiClass resolved = ((PsiClassReferenceType) psiType).resolve(); return resolved != null && resolved.isEnum(); } return false; }
@Override public boolean canHandle(PsiType psiType) { if (psiType instanceof PsiClassReferenceType) { PsiClass resolved = ((PsiClassReferenceType) psiType).resolve(); if (resolved != null && JAVA_LANG_CLASS.equals(resolved.getQualifiedName())) { return true; } } return false; }
private Stream<LookupElementBuilder> buildStream(String propertyName, PsiElement position, PsiType psiType) { for (ValueCompletionResolver completionResolver : completionResolvers) { if (completionResolver.canHandle(psiType)) { return completionResolver.resolveCompletions(propertyName, psiType); } } return Stream.empty(); }