<commit_before>package com.kalessil.phpStorm.yii2inspections.inspectors;

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 org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.util.*;

/*
 * This file is part of the Yii2 Inspections package.
 *
 * Author: <NAME> <<EMAIL>>
 *
 * 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";

    @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);
                if (parents.size() > 0) {
                    for (PhpClass parent : parents) {
                        if (parent.getFQN().equals("\\yii\\base\\Object")) {
                            supportsPropertyFeature = true;
                            break;
                        }
                    }

                    parents.clear();
                }
                if (!supportsPropertyFeature) {
                    return;
                }

                /* iterate get methods, find matching set methods */
                final Map<String, String> props = this.findPropertyCandidates(clazz);
                if (props.size() > 0) {
                    final String message = messagePattern.replace("%p%", String.join("', '", props.keySet()));
                    holder.registerProblem(nameNode, message, ProblemHighlightType.WEAK_WARNING, new TheLocalFix(props));
                }
            }

            @NotNull
            private Map<String, String> findPropertyCandidates(@NotNull PhpClass clazz) {
                final Map<String, String> properties = new HashMap<>();

                /* extract methods and operate on name-methods relations */
                final Method[] methods = clazz.getOwnMethods();
                if (null == methods || 0 == methods.length) {
                    return properties;
                }
                final Map<String, Method> mappedMethods = new HashMap<>();
                for (Method method : methods) {
                    mappedMethods.put(method.getName(), method);
                }

                /* process extracted methods*/
                for (String candidate : mappedMethods.keySet()) {
                    Method getterMethod = null;
                    Method setterMethod = null;

                    /* extract methods: get (looks up and extracts set), set (looks up get and skipped if found) */
                    if (candidate.startsWith("get")) {
                        getterMethod = mappedMethods.get(candidate);
                        if (getterMethod.isStatic() || 0 != getterMethod.getParameters().length) {
                            getterMethod = null;
                        }

                        final String complimentarySetter = candidate.replaceAll("^get", "set");
                        if (mappedMethods.containsKey(complimentarySetter)) {
                            setterMethod = mappedMethods.get(complimentarySetter);
                            if (setterMethod.isStatic() || 0 != setterMethod.getParameters().length) {
                                setterMethod = null;
                            }

                        }
                    }
                    if (candidate.startsWith("set")) {
                        setterMethod = mappedMethods.get(candidate);
                        if (setterMethod.isStatic() || 0 != setterMethod.getParameters().length) {
                            setterMethod = null;
                        }

                        final String complimentaryGetter = candidate.replaceAll("^set", "get");<commit_msg>[#15] MissingPropertyAnnotationsInspector - UTs are green<commit_after>package com.kalessil.phpStorm.yii2inspections.inspectors;

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 org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.util.*;

/*
 * This file is part of the Yii2 Inspections package.
 *
 * Author: <NAME> <<EMAIL>>
 *
 * 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";

    @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);
                if (parents.size() > 0) {
                    for (PhpClass parent : parents) {
                        if (parent.getFQN().equals("\\yii\\base\\Object")) {
                            supportsPropertyFeature = true;
                            break;
                        }
                    }

                    parents.clear();
                }
                if (!supportsPropertyFeature) {
                    return;
                }

                /* iterate get methods, find matching set methods */
                final Map<String, String> props = this.findPropertyCandidates(clazz);
                if (props.size() > 0) {
                    final String message = messagePattern.replace("%p%", String.join("', '", props.keySet()));
                    holder.registerProblem(nameNode, message, ProblemHighlightType.WEAK_WARNING, new TheLocalFix(props));
                }
            }

            @NotNull
            private Map<String, String> findPropertyCandidates(@NotNull PhpClass clazz) {
                final Map<String, String> properties = new HashMap<>();

                /* extract methods and operate on name-methods relations */
                final Method[] methods = clazz.getOwnMethods();
                if (null == methods || 0 == methods.length) {
                    return properties;
                }
                final Map<String, Method> mappedMethods = new HashMap<>();
                for (Method method : methods) {
                    mappedMethods.put(method.getName(), method);
                }

                /* process extracted methods*/
                for (String candidate : mappedMethods.keySet()) {
                    Method getterMethod = null;
                    Method setterMethod = null;

                    /* extract methods: get (looks up and extracts set), set (looks up get and skipped if found) */
                    if (candidate.startsWith("get")) {
                        getterMethod = mappedMethods.get(candidate);
                        if (getterMethod.isStatic() || 0 != getterMethod.getParameters().length) {
                            getterMethod = null;
                        }

                        final String complimentarySetter = candidate.replaceAll("^get", "set");
                        if (mappedMethods.containsKey(complimentarySetter)) {
                            setterMethod = mappedMethods.get(complimentarySetter);
                            if (setterMethod.isStatic() || 0 == setterMethod.getParameters().length) {
                                setterMethod = null;
                            }

                        }
                    }
                    if (candidate.startsWith("set")) {
                        setterMethod = mappedMethods.get(candidate);
                        if (setterMethod.isStatic() || 0 != setterMethod.getParameters().length) {
                            setterMethod = null;
                        }

                        final String complimentaryGetter = candidate.replaceAll("^set", "get");
{'fraction_non_alphanumeric': 0.08999266862170088, 'fraction_numerical': 0.0020161290322580645, 'mean_word_length': 1.8817005545286507, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1094935', 'n_tokens_mistral': 2806, 'n_tokens_neox': 2593, 'n_words': 603}