// Path: src/main/java/com/kalessil/phpStorm/yii2inspections/inspectors/utils/InheritanceChainExtractUtil.java
// final public class InheritanceChainExtractUtil {
//     @NotNull
//     public static Set<PhpClass> collect(@NotNull PhpClass clazz) {
//         final Set<PhpClass> processedItems = new HashSet<>();
// 
//         if (clazz.isInterface()) {
//             processInterface(clazz, processedItems);
//         } else {
//             processClass(clazz, processedItems);
//         }
// 
//         return processedItems;
//     }
// 
//     private static void processClass(@NotNull PhpClass clazz, @NotNull Set<PhpClass> processed) {
//         if (clazz.isInterface()) {
//             throw new InvalidParameterException("Interface shall not be provided");
//         }
//         processed.add(clazz);
// 
//         /* re-delegate interface handling */
//         for (PhpClass anInterface : clazz.getImplementedInterfaces()) {
//             processInterface(anInterface, processed);
//         }
// 
//         /* handle parent class */
//         if (null != clazz.getSuperClass()) {
//             processClass(clazz.getSuperClass(), processed);
//         }
//     }
// 
//     private static void processInterface(@NotNull PhpClass clazz, @NotNull Set<PhpClass> processed) {
//         if (!clazz.isInterface()) {
//             throw new InvalidParameterException("Class shall not be provided");
//         }
// 
//         if (processed.add(clazz)) {
//             for (PhpClass parentInterface : clazz.getImplementedInterfaces()) {
//                 processInterface(parentInterface, processed);
//             }
//         }
//     }
// }
// 
// Path: src/main/java/com/kalessil/phpStorm/yii2inspections/inspectors/utils/NamedElementUtil.java
// final public class NamedElementUtil {
// 
//     /** returns name identifier, which is valid for reporting */
//     @Nullable
//     static public PsiElement getNameIdentifier(@Nullable PsiNameIdentifierOwner element) {
//         if (null != element) {
//             PsiElement id          = element.getNameIdentifier();
//             boolean isIdReportable = null != id && id.getTextLength() > 0;
// 
//             return isIdReportable ? id : null;
//         }
// 
//         return null;
//     }
// 
// }


import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocComment;
import com.jetbrains.php.lang.inspections.PhpInspection;
import com.jetbrains.php.lang.psi.PhpPsiElementFactory;
import com.jetbrains.php.lang.psi.elements.*;
import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor;
import com.kalessil.phpStorm.yii2inspections.inspectors.utils.InheritanceChainExtractUtil;
import com.kalessil.phpStorm.yii2inspections.inspectors.utils.NamedElementUtil;
import net.miginfocom.swing.MigLayout;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.*;
package com.kalessil.phpStorm.yii2inspections.inspectors;



/*
 * This file is part of the Yii2 Inspections package.
 *
 * Author: Vladimir Reznichenko <kalessil@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

final public class MissingPropertyAnnotationsInspector extends PhpInspection {
    // configuration flags automatically saved by IDE
    @SuppressWarnings("WeakerAccess")
    public boolean REQUIRE_BOTH_GETTER_SETTER = false;

    private static final String messagePattern = "'%p%': properties needs to be annotated";

    private static final Set<String> baseObjectClasses = new HashSet<>();
    static {
        baseObjectClasses.add("\\yii\\base\\Object");
        baseObjectClasses.add("\\yii\\base\\BaseObject");
    }

    @NotNull
    public String getShortName() {
        return "MissingPropertyAnnotationsInspection";
    }

    @Override
    @NotNull
    public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
        return new PhpElementVisitor() {
            @Override
            public void visitPhpClass(PhpClass clazz) {
                /* check only regular named classes */
                final PsiElement nameNode = NamedElementUtil.getNameIdentifier(clazz);
                if (null == nameNode) {
                    return;
                }

                /* check if the class inherited from yii\base\Object */
                boolean supportsPropertyFeature = false;
// Path: src/main/java/com/kalessil/phpStorm/yii2inspections/inspectors/utils/InheritanceChainExtractUtil.java
// final public class InheritanceChainExtractUtil {
//     @NotNull
//     public static Set<PhpClass> collect(@NotNull PhpClass clazz) {
//         final Set<PhpClass> processedItems = new HashSet<>();
// 
//         if (clazz.isInterface()) {
//             processInterface(clazz, processedItems);
//         } else {
//             processClass(clazz, processedItems);
//         }
// 
//         return processedItems;
//     }
// 
//     private static void processClass(@NotNull PhpClass clazz, @NotNull Set<PhpClass> processed) {
//         if (clazz.isInterface()) {
//             throw new InvalidParameterException("Interface shall not be provided");
//         }
//         processed.add(clazz);
// 
//         /* re-delegate interface handling */
//         for (PhpClass anInterface : clazz.getImplementedInterfaces()) {
//             processInterface(anInterface, processed);
//         }
// 
//         /* handle parent class */
//         if (null != clazz.getSuperClass()) {
//             processClass(clazz.getSuperClass(), processed);
//         }
//     }
// 
//     private static void processInterface(@NotNull PhpClass clazz, @NotNull Set<PhpClass> processed) {
//         if (!clazz.isInterface()) {
//             throw new InvalidParameterException("Class shall not be provided");
//         }
// 
//         if (processed.add(clazz)) {
//             for (PhpClass parentInterface : clazz.getImplementedInterfaces()) {
//                 processInterface(parentInterface, processed);
//             }
//         }
//     }
// }
// 
// Path: src/main/java/com/kalessil/phpStorm/yii2inspections/inspectors/utils/NamedElementUtil.java
// final public class NamedElementUtil {
// 
//     /** returns name identifier, which is valid for reporting */
//     @Nullable
//     static public PsiElement getNameIdentifier(@Nullable PsiNameIdentifierOwner element) {
//         if (null != element) {
//             PsiElement id          = element.getNameIdentifier();
//             boolean isIdReportable = null != id && id.getTextLength() > 0;
// 
//             return isIdReportable ? id : null;
//         }
// 
//         return null;
//     }
// 
// }


// Path: src/main/java/com/kalessil/phpStorm/yii2inspections/inspectors/MissingPropertyAnnotationsInspector.java
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocComment;
import com.jetbrains.php.lang.inspections.PhpInspection;
import com.jetbrains.php.lang.psi.PhpPsiElementFactory;
import com.jetbrains.php.lang.psi.elements.*;
import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor;
import com.kalessil.phpStorm.yii2inspections.inspectors.utils.InheritanceChainExtractUtil;
import com.kalessil.phpStorm.yii2inspections.inspectors.utils.NamedElementUtil;
import net.miginfocom.swing.MigLayout;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.*;

package com.kalessil.phpStorm.yii2inspections.inspectors;



/*
 * This file is part of the Yii2 Inspections package.
 *
 * Author: Vladimir Reznichenko <kalessil@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

final public class MissingPropertyAnnotationsInspector extends PhpInspection {
    // configuration flags automatically saved by IDE
    @SuppressWarnings("WeakerAccess")
    public boolean REQUIRE_BOTH_GETTER_SETTER = false;

    private static final String messagePattern = "'%p%': properties needs to be annotated";

    private static final Set<String> baseObjectClasses = new HashSet<>();
    static {
        baseObjectClasses.add("\\yii\\base\\Object");
        baseObjectClasses.add("\\yii\\base\\BaseObject");
    }

    @NotNull
    public String getShortName() {
        return "MissingPropertyAnnotationsInspection";
    }

    @Override
    @NotNull
    public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
        return new PhpElementVisitor() {
            @Override
            public void visitPhpClass(PhpClass clazz) {
                /* check only regular named classes */
                final PsiElement nameNode = NamedElementUtil.getNameIdentifier(clazz);
                if (null == nameNode) {
                    return;
                }

                /* check if the class inherited from yii\base\Object */
                boolean supportsPropertyFeature = false;
                final Set<PhpClass> parents     = InheritanceChainExtractUtil.collect(clazz);