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");
}
}
}
}
}
}
}
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);
}
}
}
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));
}
}
}
};
}
Aggregations