use of com.jetbrains.php.PhpIndex in project phpinspectionsea by kalessil.
the class OffsetOperationsInspector method isContainerSupportsArrayAccess.
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean isContainerSupportsArrayAccess(@NotNull ArrayAccessExpression expression, @NotNull Set<String> indexTypesSupported) {
// ok JB parses `$var[]= ...` always as array, lets make it working properly and report them later
final PsiElement container = expression.getValue();
if (null == container) {
return false;
}
final Set<String> containerTypes = new HashSet<>();
if (container instanceof PhpTypedElement) {
final PhpType type = OpenapiResolveUtil.resolveType((PhpTypedElement) container, container.getProject());
if (type != null && !type.hasUnknown()) {
type.getTypes().forEach(t -> containerTypes.add(Types.getType(t)));
}
}
/* === cleanup resolved types === */
if (containerTypes.contains(Types.strMixed)) {
// mixed are not analyzable
containerTypes.clear();
return true;
}
if (containerTypes.size() == 2 && containerTypes.contains(Types.strString)) {
final boolean isForeachKeyType = containerTypes.contains(Types.strInteger);
final boolean isCoreApiStringType = containerTypes.contains(Types.strBoolean);
if (isForeachKeyType || isCoreApiStringType) {
containerTypes.clear();
return true;
}
}
if (containerTypes.contains(Types.strCallable)) {
// treat callable as array
containerTypes.remove(Types.strCallable);
containerTypes.add(Types.strArray);
containerTypes.add(Types.strString);
}
// don't process nulls
containerTypes.remove(Types.strNull);
// don't process generalized objects
containerTypes.remove(Types.strObject);
// don't process mysterious empty set type
containerTypes.remove(Types.strEmptySet);
/* === if we could not resolve container, do nothing === */
if (containerTypes.isEmpty()) {
return true;
}
final Project project = container.getProject();
final PhpIndex index = PhpIndex.getInstance(project);
boolean supportsOffsets = false;
for (final String typeToCheck : containerTypes) {
// commonly used case: string and array
if (typeToCheck.equals(Types.strArray) || typeToCheck.equals(Types.strString)) {
supportsOffsets = true;
/* here we state which regular index types we want to promote */
indexTypesSupported.add(Types.strString);
indexTypesSupported.add(Types.strInteger);
continue;
}
// some of possible types are scalars, what's wrong
if (!typeToCheck.isEmpty() && typeToCheck.charAt(0) != '\\') {
supportsOffsets = false;
break;
}
// now we are at point when analyzing classes only
final List<PhpClass> classes = OpenapiResolveUtil.resolveClassesAndInterfacesByFQN(typeToCheck, index);
for (final PhpClass clazz : classes) {
/* custom offsets management, follow annotated types */
for (final String methodName : Arrays.asList("offsetGet", "offsetSet", "__get", "__set")) {
final Method method = OpenapiResolveUtil.resolveMethod(clazz, methodName);
if (method != null) {
/* regular array index types can be applied */
if (methodName.startsWith("__")) {
indexTypesSupported.add(Types.strString);
indexTypesSupported.add(Types.strInteger);
} else /* user-defined index types can be applied */
{
final Parameter[] parameters = method.getParameters();
if (parameters.length > 0) {
final PhpType type = OpenapiResolveUtil.resolveType(parameters[0], project);
if (type != null) {
type.filterUnknown().getTypes().forEach(t -> indexTypesSupported.add(Types.getType(t)));
}
}
}
supportsOffsets = true;
}
}
}
classes.clear();
}
// when might not support offset access, reuse types container to report back why
if (!supportsOffsets) {
indexTypesSupported.clear();
indexTypesSupported.addAll(containerTypes);
}
containerTypes.clear();
return supportsOffsets;
}
use of com.jetbrains.php.PhpIndex in project phpinspectionsea by kalessil.
the class ComparableCoreClassesStrategy method isComparableObject.
private static boolean isComparableObject(@NotNull PsiElement operand, @NotNull PhpIndex index) {
/* extract types of operand, check if classes are/inherited from \DateTime */
final Set<String> operandTypes = new HashSet<>();
if (operand instanceof PhpTypedElement) {
final PhpType resolved = OpenapiResolveUtil.resolveType((PhpTypedElement) operand, operand.getProject());
if (resolved != null) {
resolved.filterUnknown().getTypes().forEach(t -> operandTypes.add(Types.getType(t)));
}
}
if (!TypesSemanticsUtil.isNullableObjectInterface(operandTypes)) {
operandTypes.clear();
return false;
}
/* collect classes to check for \DateTime relationship */
final List<PhpClass> operandClasses = new ArrayList<>();
operandTypes.stream().filter(fqn -> fqn.charAt(0) == '\\').forEach(fqn -> operandClasses.addAll(OpenapiResolveUtil.resolveClassesAndInterfacesByFQN(fqn, index)));
operandTypes.clear();
/* inspect classes for being a/child of special once */
for (final PhpClass clazz : operandClasses) {
final HashSet<PhpClass> hierarchy = InterfacesExtractUtil.getCrawlInheritanceTree(clazz, true);
for (final PhpClass oneClass : hierarchy) {
if (comparableObjects.contains(oneClass.getFQN())) {
return true;
}
}
hierarchy.clear();
}
operandClasses.clear();
return false;
}
use of com.jetbrains.php.PhpIndex in project yii2support by nvlad.
the class MissingActiveRecordInActiveQueryInspection method buildVisitor.
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean isOnTheFly) {
return new PhpElementVisitor() {
@Override
public void visitPhpClass(PhpClass clazz) {
if (clazz.getSuperClass() != null && clazz.getSuperClass().getFQN().equals("\\yii\\db\\ActiveQuery")) {
PhpIndex index = PhpIndex.getInstance(clazz.getProject());
PhpClass activeRecordClass = ClassUtils.findClassInSeeTags(index, clazz, "\\yii\\db\\BaseActiveRecord");
if (activeRecordClass == null) {
problemsHolder.registerProblem(clazz.getFirstChild(), "Can not find connected ActiveRecord class.\nYou should add @see tag with linked ActiveRecord", ProblemHighlightType.WEAK_WARNING);
}
}
super.visitPhpClass(clazz);
}
};
}
use of com.jetbrains.php.PhpIndex in project yii2support by nvlad.
the class ViewUtil method isValidRenderMethod.
public static boolean isValidRenderMethod(MethodReference methodReference) {
final PhpClass clazz = ClassUtils.getPhpClassByCallChain(methodReference);
if (clazz == null) {
return false;
}
final PhpIndex phpIndex = PhpIndex.getInstance(clazz.getProject());
return ClassUtils.isClassInheritsOrEqual(clazz, "\\yii\\base\\Controller", phpIndex) || ClassUtils.isClassInheritsOrEqual(clazz, "\\yii\\base\\View", phpIndex) || ClassUtils.isClassInheritsOrEqual(clazz, "\\yii\\base\\Widget", phpIndex) || ClassUtils.isClassInheritsOrEqual(clazz, "\\yii\\mail\\BaseMailer", phpIndex);
}
use of com.jetbrains.php.PhpIndex in project idea-php-typo3-plugin by cedricziel.
the class TCAUtil method findAvailableRenderTypes.
private static Set<PsiElement> findAvailableRenderTypes(Project project) {
PhpIndex phpIndex = PhpIndex.getInstance(project);
PsiFile[] extLocalConfFiles = FilenameIndex.getFilesByName(project, EXT_LOCALCONF_FILENAME, GlobalSearchScope.allScope(project));
Collection<PhpClass> nodeRegistries = phpIndex.getClassesByFQN(NODE_FACTORY_CLASS);
Set<PsiElement> elements = new HashSet<>();
for (PhpClass registry : nodeRegistries) {
Collections.addAll(elements, PsiTreeUtil.collectElements(registry, element -> PlatformPatterns.psiElement(StringLiteralExpression.class).withParent(PlatformPatterns.psiElement(PhpElementTypes.ARRAY_KEY).withAncestor(3, PlatformPatterns.psiElement(PhpElementTypes.CLASS_FIELD).withName("nodeTypes"))).accepts(element)));
}
for (PsiFile file : extLocalConfFiles) {
Collections.addAll(elements, PsiTreeUtil.collectElements(file, element -> PlatformPatterns.psiElement(StringLiteralExpression.class).withParent(PlatformPatterns.psiElement(PhpElementTypes.ARRAY_VALUE).withParent(PlatformPatterns.psiElement(PhpElementTypes.HASH_ARRAY_ELEMENT).withChild(PlatformPatterns.psiElement(PhpElementTypes.ARRAY_KEY).withText("'nodeName'")))).accepts(element)));
}
return elements;
}
Aggregations