Search in sources :

Example 1 with AnnotateFix

use of org.intellij.plugins.intelliLang.util.AnnotateFix in project intellij-community by JetBrains.

the class LanguageMismatch method checkExpression.

void checkExpression(PsiExpression expression, ProblemsHolder holder, Pair<String, ? extends Set<String>> annotationName) {
    final PsiType type = expression.getType();
    if (type == null || !PsiUtilEx.isStringOrStringArray(type)) {
        return;
    }
    final PsiModifierListOwner contextOwner = AnnotationUtilEx.getAnnotatedElementFor(expression, AnnotationUtilEx.LookupType.CONTEXT_ONLY);
    if (contextOwner != null && PsiUtilEx.isLanguageAnnotationTarget(contextOwner)) {
        final PsiAnnotation[] annotations = AnnotationUtilEx.getAnnotationFrom(contextOwner, annotationName, true);
        if (annotations.length > 0) {
            final String expected = AnnotationUtilEx.calcAnnotationValue(annotations, "value");
            if (expected != null) {
                final PsiModifierListOwner declOwner = AnnotationUtilEx.getAnnotatedElementFor(expression, AnnotationUtilEx.LookupType.PREFER_DECLARATION);
                if (declOwner != null && PsiUtilEx.isLanguageAnnotationTarget(declOwner)) {
                    final PsiAnnotation[] as = AnnotationUtilEx.getAnnotationFrom(declOwner, annotationName, true);
                    if (as.length > 0) {
                        final String actual = AnnotationUtilEx.calcAnnotationValue(as, "value");
                        if (!expected.equals(actual)) {
                            // language annotation values from context and declaration don't match
                            holder.registerProblem(expression, "Language mismatch: Expected '" + expected + "', got '" + actual + "'");
                        }
                    } else if (CHECK_NON_ANNOTATED_REFERENCES) {
                        final PsiElement var = PsiTreeUtil.getParentOfType(expression, PsiVariable.class, PsiExpressionList.class, PsiAssignmentExpression.class);
                        // only nag about direct assignment or passing the reference as parameter
                        if (var instanceof PsiVariable) {
                            if (((PsiVariable) var).getInitializer() != expression) {
                                return;
                            }
                        } else if (var instanceof PsiExpressionList) {
                            final PsiExpressionList list = (PsiExpressionList) var;
                            if (Arrays.asList(list.getExpressions()).indexOf(expression) == -1) {
                                return;
                            }
                        } else if (var instanceof PsiAssignmentExpression) {
                            final PsiAssignmentExpression a = (PsiAssignmentExpression) var;
                            if (a.getRExpression() != expression) {
                                return;
                            }
                        }
                        if (declOwner instanceof PsiField && CollectionUtils.isConstantEmptyArray((PsiField) declOwner)) {
                            // don't warn about unannotated empty array constants.
                            return;
                        }
                        // context implies language, but declaration isn't annotated
                        if (AnnotateFix.canApplyOn(declOwner)) {
                            final PsiAnnotation annotation = annotations[annotations.length - 1];
                            final String initializer = annotation.getParameterList().getText();
                            final AnnotateFix fix = new AnnotateFix(annotation.getQualifiedName(), initializer) {

                                @Override
                                @NotNull
                                public String getName() {
                                    return initializer == null ? super.getName() : super.getName() + initializer;
                                }
                            };
                            holder.registerProblem(expression, "Language problem: Found non-annotated reference where '" + expected + "' is expected", fix);
                        } else {
                            holder.registerProblem(expression, "Language problem: Found non-annotated reference where '" + expected + "' is expected");
                        }
                    }
                }
            }
        }
    }
}
Also used : NotNull(org.jetbrains.annotations.NotNull) AnnotateFix(org.intellij.plugins.intelliLang.util.AnnotateFix)

Example 2 with AnnotateFix

use of org.intellij.plugins.intelliLang.util.AnnotateFix in project intellij-community by JetBrains.

the class PatternValidator method checkExpression.

private void checkExpression(PsiExpression expression, final PsiAnnotation[] annotations, ProblemsHolder holder) {
    if (annotations.length == 0)
        return;
    final PsiAnnotation psiAnnotation = annotations[0];
    // cache compiled pattern with annotation
    CachedValue<Pattern> p = psiAnnotation.getUserData(COMPLIED_PATTERN);
    if (p == null) {
        final CachedValueProvider<Pattern> provider = () -> {
            final String pattern = AnnotationUtilEx.calcAnnotationValue(psiAnnotation, "value");
            Pattern p1 = null;
            if (pattern != null) {
                try {
                    p1 = Pattern.compile(pattern);
                } catch (PatternSyntaxException e) {
                // pattern stays null
                }
            }
            return CachedValueProvider.Result.create(p1, (Object[]) annotations);
        };
        p = CachedValuesManager.getManager(expression.getProject()).createCachedValue(provider, false);
        psiAnnotation.putUserData(COMPLIED_PATTERN, p);
    }
    final Pattern pattern = p.getValue();
    if (pattern == null)
        return;
    List<PsiExpression> nonConstantElements = new SmartList<>();
    final Object result = new SubstitutedExpressionEvaluationHelper(expression.getProject()).computeExpression(expression, myConfiguration.getAdvancedConfiguration().getDfaOption(), false, nonConstantElements);
    final String o = result == null ? null : String.valueOf(result);
    if (o != null) {
        if (!pattern.matcher(o).matches()) {
            if (annotations.length > 1) {
                // the last element contains the element's actual annotation
                final String fqn = annotations[annotations.length - 1].getQualifiedName();
                assert fqn != null;
                final String name = StringUtil.getShortName(fqn);
                holder.registerProblem(expression, MessageFormat.format("Expression ''{0}'' doesn''t match ''{1}'' pattern: {2}", o, name, pattern.pattern()));
            } else {
                holder.registerProblem(expression, MessageFormat.format("Expression ''{0}'' doesn''t match pattern: {1}", o, pattern.pattern()));
            }
        }
    } else if (CHECK_NON_CONSTANT_VALUES) {
        for (PsiExpression expr : nonConstantElements) {
            final PsiElement e;
            if (expr instanceof PsiReferenceExpression) {
                e = ((PsiReferenceExpression) expr).resolve();
            } else if (expr instanceof PsiMethodCallExpression) {
                e = ((PsiMethodCallExpression) expr).getMethodExpression().resolve();
            } else {
                e = expr;
            }
            final PsiModifierListOwner owner = e instanceof PsiModifierListOwner ? (PsiModifierListOwner) e : null;
            LocalQuickFix quickFix;
            if (owner != null && PsiUtilEx.isLanguageAnnotationTarget(owner)) {
                PsiAnnotation[] resolvedAnnos = AnnotationUtilEx.getAnnotationFrom(owner, myConfiguration.getAdvancedConfiguration().getPatternAnnotationPair(), true);
                if (resolvedAnnos.length == 2 && annotations.length == 2 && Comparing.strEqual(resolvedAnnos[1].getQualifiedName(), annotations[1].getQualifiedName())) {
                    // both target and source annotated indirectly with the same anno
                    return;
                }
                final String classname = myConfiguration.getAdvancedConfiguration().getSubstAnnotationPair().first;
                quickFix = AnnotateFix.canApplyOn(owner) ? new AnnotateFix(classname) : new IntroduceVariableFix();
            } else {
                quickFix = new IntroduceVariableFix();
            }
            holder.registerProblem(expr, "Unsubstituted expression", quickFix);
        }
    }
}
Also used : Pattern(java.util.regex.Pattern) LocalQuickFix(com.intellij.codeInspection.LocalQuickFix) SubstitutedExpressionEvaluationHelper(org.intellij.plugins.intelliLang.util.SubstitutedExpressionEvaluationHelper) SmartList(com.intellij.util.SmartList) AnnotateFix(org.intellij.plugins.intelliLang.util.AnnotateFix) PatternSyntaxException(java.util.regex.PatternSyntaxException)

Example 3 with AnnotateFix

use of org.intellij.plugins.intelliLang.util.AnnotateFix in project intellij-community by JetBrains.

the class PatternOverriddenByNonAnnotatedMethod method buildVisitor.

@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
    return new JavaElementVisitor() {

        final Pair<String, ? extends Set<String>> annotationName = Configuration.getProjectInstance(holder.getProject()).getAdvancedConfiguration().getPatternAnnotationPair();

        @Override
        public void visitMethod(PsiMethod method) {
            final PsiIdentifier psiIdentifier = method.getNameIdentifier();
            if (psiIdentifier == null || !PsiUtilEx.isLanguageAnnotationTarget(method)) {
                return;
            }
            final PsiAnnotation[] annotationFrom = AnnotationUtilEx.getAnnotationFrom(method, annotationName, true, false);
            if (annotationFrom.length == 0) {
                final PsiAnnotation[] annotationFromHierarchy = AnnotationUtilEx.getAnnotationFrom(method, annotationName, true, true);
                if (annotationFromHierarchy.length > 0) {
                    final String annotationClassname = annotationFromHierarchy[annotationFromHierarchy.length - 1].getQualifiedName();
                    final String argList = annotationFromHierarchy[annotationFromHierarchy.length - 1].getParameterList().getText();
                    holder.registerProblem(psiIdentifier, "Non-annotated Method overrides @Pattern Method", new AnnotateFix(annotationClassname, argList));
                }
            }
        }
    };
}
Also used : Set(java.util.Set) AnnotateFix(org.intellij.plugins.intelliLang.util.AnnotateFix) Pair(com.intellij.openapi.util.Pair) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

AnnotateFix (org.intellij.plugins.intelliLang.util.AnnotateFix)3 NotNull (org.jetbrains.annotations.NotNull)2 LocalQuickFix (com.intellij.codeInspection.LocalQuickFix)1 Pair (com.intellij.openapi.util.Pair)1 SmartList (com.intellij.util.SmartList)1 Set (java.util.Set)1 Pattern (java.util.regex.Pattern)1 PatternSyntaxException (java.util.regex.PatternSyntaxException)1 SubstitutedExpressionEvaluationHelper (org.intellij.plugins.intelliLang.util.SubstitutedExpressionEvaluationHelper)1