inspection and quickfix to add <with> tags to <extensionPoint> declarations

This commit is contained in:
Dmitry Jemerov
2013-02-12 22:22:32 +01:00
parent aa54cd2a26
commit 34aab5599b
6 changed files with 173 additions and 9 deletions
@@ -78,6 +78,13 @@
enabledByDefault="true"
level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.InspectionMappingConsistencyInspection"/>
<localInspection language="XML" shortName="ExtensionPointBeanClass"
bundle="org.jetbrains.idea.devkit.DevKitBundle"
groupKey="inspections.group.name"
displayName="&lt;extensionPoint&gt; beanClass specification"
enabledByDefault="true"
level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.ExtensionPointBeanClassInspection"/>
<moduleConfigurationEditorProvider implementation="org.jetbrains.idea.devkit.module.PluginModuleEditorsProvider"/>
<implicitUsageProvider implementation="org.jetbrains.idea.devkit.inspections.DevKitEntryPoints"/>
@@ -0,0 +1,6 @@
<html>
<body>
Ensures that an &lt;extensionPoint&gt; tag has &lt;with&gt; subtags specifying types for all class fields.
<!-- tooltip end -->
</body>
</html>
@@ -56,4 +56,6 @@ public interface ExtensionPoint extends DomElement {
@NotNull
@SubTagList("with")
List<With> getWithElements();
With addWith();
}
@@ -68,21 +68,25 @@ public class PluginFieldNameConverter extends ResolvingConverter<PsiField> {
}
private static PsiField findFieldByAttributeValue(PsiClass psiClass, @NotNull String attrNameToFind) {
final PsiConstantEvaluationHelper evalHelper = JavaPsiFacade.getInstance(psiClass.getProject()).getConstantEvaluationHelper();
for (PsiField psiField : psiClass.getAllFields()) {
final PsiMethod getter = PropertyUtils.findGetterForField(psiField);
final PsiMethod setter = PropertyUtils.findSetterForField(psiField);
final PsiAnnotation attrAnno = ExtensionDomExtender.findAnnotation(Attribute.class, psiField, getter, setter);
if (attrAnno != null) {
final String attrName = ExtensionDomExtender.getStringAttribute(attrAnno, "value", evalHelper);
if (attrNameToFind.equals(attrName)) {
return psiField;
}
if (attrNameToFind.equals(getAttributeAnnotationValue(psiField))) {
return psiField;
}
}
return null;
}
public static String getAttributeAnnotationValue(PsiField psiField) {
final PsiConstantEvaluationHelper evalHelper = JavaPsiFacade.getInstance(psiField.getProject()).getConstantEvaluationHelper();
final PsiMethod getter = PropertyUtils.findGetterForField(psiField);
final PsiMethod setter = PropertyUtils.findSetterForField(psiField);
final PsiAnnotation attrAnno = ExtensionDomExtender.findAnnotation(Attribute.class, psiField, getter, setter);
if (attrAnno != null) {
return ExtensionDomExtender.getStringAttribute(attrAnno, "value", evalHelper);
}
return null;
}
@Nullable
@Override
public String toString(@Nullable PsiField field, ConvertContext context) {
@@ -0,0 +1,70 @@
/*
* 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.idea.devkit.inspections;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiField;
import com.intellij.psi.XmlElementVisitor;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.devkit.dom.ExtensionPoint;
import org.jetbrains.idea.devkit.dom.impl.ExtensionDomExtender;
import org.jetbrains.idea.devkit.inspections.quickfix.AddWithTagFix;
import java.util.ArrayList;
import java.util.List;
/**
* @author yole
*/
public class ExtensionPointBeanClassInspection extends DevKitInspectionBase {
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new XmlElementVisitor() {
@Override
public void visitXmlTag(XmlTag tag) {
DomElement element = DomUtil.getDomElement(tag);
if (element instanceof ExtensionPoint) {
ExtensionPoint extensionPoint = (ExtensionPoint)element;
if (extensionPoint.getWithElements().isEmpty() && !collectMissingWithTags(extensionPoint).isEmpty()) {
holder.registerProblem(tag,
"<extensionPoint> does not have <with> tags to specify the types of class fields",
new AddWithTagFix());
}
}
}
};
}
public static List<PsiField> collectMissingWithTags(ExtensionPoint element) {
final List<PsiField> result = new ArrayList<PsiField>();
PsiClass beanClass = element.getBeanClass().getValue();
if (beanClass != null) {
for (PsiField field : beanClass.getAllFields()) {
if (ExtensionDomExtender.isClassField(field.getName()) &&
ExtensionDomExtender.findWithElement(element.getWithElements(), field) == null) {
result.add(field);
}
}
}
return result;
}
}
@@ -0,0 +1,75 @@
/*
* 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.idea.devkit.inspections.quickfix;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.util.PsiNavigateUtil;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.devkit.dom.ExtensionPoint;
import org.jetbrains.idea.devkit.dom.With;
import org.jetbrains.idea.devkit.dom.impl.PluginFieldNameConverter;
import org.jetbrains.idea.devkit.inspections.ExtensionPointBeanClassInspection;
import java.util.List;
/**
* @author yole
*/
public class AddWithTagFix implements LocalQuickFix {
@NotNull
@Override
public String getName() {
return "Add <with> tag";
}
@NotNull
@Override
public String getFamilyName() {
return getName();
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
DomElement element = DomUtil.getDomElement(descriptor.getPsiElement());
if (!(element instanceof ExtensionPoint)) {
return;
}
ExtensionPoint extensionPoint = (ExtensionPoint)element;
List<PsiField> fields = ExtensionPointBeanClassInspection.collectMissingWithTags(extensionPoint);
PsiElement navTarget = null;
for (PsiField field : fields) {
String attributeName = PluginFieldNameConverter.getAttributeAnnotationValue(field);
if (attributeName == null) {
attributeName = field.getName();
}
With with = extensionPoint.addWith();
with.getAttribute().setStringValue(attributeName);
with.getImplements().setStringValue("");
if (navTarget == null) {
navTarget = with.getImplements().getXmlAttributeValue();
}
}
if (navTarget != null) {
PsiNavigateUtil.navigate(navTarget);
}
}
}