mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-101798 DelegatesTo : report unused @DelegatesTo.Target annotations
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
<font face="verdana" size="-1">
|
||||
This inspection checks @groovy.lang.DelegatesTo annotation arguments.
|
||||
</font>
|
||||
</body>
|
||||
</html>
|
||||
@@ -994,6 +994,10 @@
|
||||
groupName="Annotations verifying" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="org.jetbrains.plugins.groovy.annotator.inspections.GroovySingletonAnnotationInspection"/>
|
||||
|
||||
<localInspection language="Groovy" groupPath="Groovy" shortName="DelegatesTo" displayName="@DelegatesTo inspection"
|
||||
groupName="Annotations verifying" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="org.jetbrains.plugins.groovy.codeInspection.confusing.DelegatesToInspection"/>
|
||||
|
||||
<implicitUsageProvider implementation="org.jetbrains.plugins.groovy.gpp.GppImplicitUsageProvider"/>
|
||||
<implicitUsageProvider implementation="org.jetbrains.plugins.groovy.findUsages.GrImplicitUsageProvider"/>
|
||||
|
||||
|
||||
+3
-1
@@ -102,4 +102,6 @@ gr.package=Package mismatch
|
||||
java.style.property.access=Java-style accessor invocation
|
||||
type.customizer.is.not.marked.as.a.resource.file=Type customizer script is not marked as compiler resources
|
||||
add.to.resources=Add to resources
|
||||
add.type.customizer.to.resources=Add type customizer script to resources
|
||||
add.type.customizer.to.resources=Add type customizer script to resources
|
||||
target.0.does.not.exist=Target ''{0}'' does not exist
|
||||
target.annotation.is.unused=@Target is unused
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.codeInspection.confusing;
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.psi.PsiAnnotation;
|
||||
import com.intellij.psi.PsiAnnotationMemberValue;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrAnnotationUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class DelegatesToInspection extends BaseInspection {
|
||||
@NotNull
|
||||
@Override
|
||||
protected BaseInspectionVisitor buildVisitor() {
|
||||
return new BaseInspectionVisitor() {
|
||||
@Override
|
||||
public void visitAnnotation(GrAnnotation annotation) {
|
||||
checkTarget(annotation);
|
||||
checkDelegatesTo(annotation);
|
||||
}
|
||||
|
||||
private void checkTarget(GrAnnotation annotation) {
|
||||
if (!GroovyCommonClassNames.GROOVY_LANG_DELEGATES_TO_TARGET.equals(annotation.getQualifiedName())) return;
|
||||
|
||||
|
||||
final PsiElement owner = annotation.getParent().getParent();
|
||||
if (!(owner instanceof GrParameter)) return;
|
||||
|
||||
|
||||
final boolean isTargetDeclared = annotation.findDeclaredAttributeValue("value") != null;
|
||||
String targetName = GrAnnotationUtil.inferStringAttribute(annotation, "value");
|
||||
|
||||
final GrParameterList parameterList = DefaultGroovyMethods.asType(owner.getParent(), GrParameterList.class);
|
||||
for (GrParameter parameter : parameterList.getParameters()) {
|
||||
final PsiAnnotation delegatesTo = parameter.getModifierList().findAnnotation(GroovyCommonClassNames.GROOVY_LANG_DELEGATES_TO);
|
||||
if (delegatesTo != null) {
|
||||
if (isTargetDeclared) {
|
||||
final String curTarget = GrAnnotationUtil.inferStringAttribute(delegatesTo, "target");
|
||||
if (curTarget != null && curTarget.equals(targetName)) {
|
||||
return; //target is used
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (delegatesTo.findDeclaredAttributeValue("target") == null) {
|
||||
return; // target is used
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerError(annotation.getClassReference(), GroovyInspectionBundle.message("target.annotation.is.unused"),
|
||||
LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
}
|
||||
|
||||
private void checkDelegatesTo(GrAnnotation annotation) {
|
||||
if (!GroovyCommonClassNames.GROOVY_LANG_DELEGATES_TO.equals(annotation.getQualifiedName())) return;
|
||||
|
||||
final PsiElement owner = annotation.getParent().getParent();
|
||||
if (!(owner instanceof GrParameter)) return;
|
||||
|
||||
final PsiAnnotationMemberValue targetPair = annotation.findDeclaredAttributeValue("target");
|
||||
if (targetPair == null) return;
|
||||
|
||||
String targetName = GrAnnotationUtil.inferStringAttribute(annotation, "target");
|
||||
|
||||
final GrParameterList parameterList = DefaultGroovyMethods.asType(owner.getParent(), GrParameterList.class);
|
||||
for (GrParameter parameter : parameterList.getParameters()) {
|
||||
final PsiAnnotation target = parameter.getModifierList().findAnnotation(GroovyCommonClassNames.GROOVY_LANG_DELEGATES_TO_TARGET);
|
||||
if (target != null) {
|
||||
final String curTarget = GrAnnotationUtil.inferStringAttribute(target, "value");
|
||||
if (curTarget != null && curTarget.equals(targetName)) {
|
||||
return; //target is used
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerError(targetPair, GroovyInspectionBundle.message("target.0.does.not.exist", targetName != null ? targetName : "?"),
|
||||
LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl;
|
||||
|
||||
import com.intellij.psi.PsiAnnotation;
|
||||
import com.intellij.psi.PsiAnnotationMemberValue;
|
||||
import com.intellij.psi.PsiLiteral;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class GrAnnotationUtil {
|
||||
@Nullable
|
||||
public static String inferStringAttribute(@NotNull PsiAnnotation annotation, @NotNull String attributeName) {
|
||||
final PsiAnnotationMemberValue targetValue = annotation.findAttributeValue(attributeName);
|
||||
if (targetValue instanceof PsiLiteral) {
|
||||
final Object value = ((PsiLiteral)targetValue).getValue();
|
||||
if (value instanceof String) return (String)value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+3
-13
@@ -29,6 +29,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrAnnotationUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
@@ -106,7 +107,7 @@ public class GrDelegatesToUtil {
|
||||
else if (value == null ||
|
||||
value instanceof PsiLiteralExpression && ((PsiLiteralExpression)value).getType() == PsiType.NULL ||
|
||||
value instanceof GrLiteral && ((GrLiteral)value).getType() == PsiType.NULL) {
|
||||
String target = inferStringAttribute(delegatesTo, "target");
|
||||
String target = GrAnnotationUtil.inferStringAttribute(delegatesTo, "target");
|
||||
if (target == null) return null;
|
||||
|
||||
final int parameter = findTargetParameter(delegatesTo, target);
|
||||
@@ -132,7 +133,7 @@ public class GrDelegatesToUtil {
|
||||
final PsiAnnotation targetAnnotation = modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_LANG_DELEGATES_TO_TARGET);
|
||||
if (targetAnnotation == null) continue;
|
||||
|
||||
final String value = inferStringAttribute(targetAnnotation, "value");
|
||||
final String value = GrAnnotationUtil.inferStringAttribute(targetAnnotation, "value");
|
||||
if (value == null) continue;
|
||||
|
||||
if (value.equals(target)) return i;
|
||||
@@ -141,17 +142,6 @@ public class GrDelegatesToUtil {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String inferStringAttribute(@NotNull PsiAnnotation annotation, @NotNull String attributeName) {
|
||||
final PsiAnnotationMemberValue targetValue = annotation.findAttributeValue(attributeName);
|
||||
if (targetValue instanceof PsiLiteral) {
|
||||
final Object value = ((PsiLiteral)targetValue).getValue();
|
||||
if (value instanceof String) return (String)value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GrExpression inferCallQualifier(@NotNull GrMethodCall call) {
|
||||
final GrExpression expression = call.getInvokedExpression();
|
||||
|
||||
+30
@@ -225,4 +225,34 @@ class I{
|
||||
}
|
||||
''', GrMethodMayBeStaticInspection)
|
||||
}
|
||||
|
||||
void testDelegatesTo() {
|
||||
testHighlighting('''
|
||||
|
||||
def with1(@DelegatesTo.Target() Object target, @DelegatesTo() Closure arg) { //unused
|
||||
arg.delegate = target
|
||||
arg()
|
||||
}
|
||||
|
||||
def with2(@<warning descr="@Target is unused">DelegatesTo.Target</warning>('abc') Object target, @DelegatesTo() Closure arg) { //unused
|
||||
arg.delegate = target
|
||||
arg()
|
||||
}
|
||||
|
||||
def with3(@DelegatesTo.Target('abc') Object target, @DelegatesTo(target='abc') Closure arg) { //unused
|
||||
arg.delegate = target
|
||||
arg()
|
||||
}
|
||||
|
||||
def with4(@<warning descr="@Target is unused">DelegatesTo.Target</warning>('abcd') Object target, @DelegatesTo(target=<warning descr="Target 'abc' does not exist">'abc'</warning>) Closure arg) { //unused
|
||||
arg.delegate = target
|
||||
arg()
|
||||
}
|
||||
|
||||
def with5(@<warning descr="@Target is unused">DelegatesTo.Target</warning>() Object target, @DelegatesTo(target=<warning descr="Target 'abc' does not exist">'abc'</warning>) Closure arg) { //unused
|
||||
arg.delegate = target
|
||||
arg()
|
||||
}
|
||||
''', DelegatesToInspection)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user