ability to configure Nullable/NotNull annotations (IDEA-64677)

This commit is contained in:
anna
2011-01-26 18:20:51 +01:00
parent a834207137
commit 3b1d59b875
25 changed files with 575 additions and 132 deletions
@@ -22,6 +22,7 @@
package com.intellij.compiler.impl.javaCompiler;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.compiler.*;
import com.intellij.compiler.classParsing.AnnotationConstantValue;
import com.intellij.compiler.classParsing.MethodInfo;
@@ -827,7 +828,7 @@ public class BackendCompilerWrapper {
FileObject path = myPaths.take();
if (path == myStopThreadToken) break;
processPath(path);
processPath(path, myProject);
}
}
catch (InterruptedException e) {
@@ -852,7 +853,7 @@ public class BackendCompilerWrapper {
myPaths.offer(myStopThreadToken);
}
private void processPath(FileObject fileObject) throws CacheCorruptedException {
private void processPath(FileObject fileObject, Project project) throws CacheCorruptedException {
File file = fileObject.getFile();
final String path = file.getPath();
try {
@@ -866,7 +867,7 @@ public class BackendCompilerWrapper {
final String qName = dependencyCache.resolve(newClassQName);
String relativePathToSource = "/" + MakeUtil.createRelativePathToSource(qName, sourceFileName);
putName(sourceFileName, newClassQName, relativePathToSource, path);
boolean haveToInstrument = myAddNotNullAssertions && hasNotNullAnnotations(newClassesCache, dependencyCache.getSymbolTable(), newClassQName);
boolean haveToInstrument = myAddNotNullAssertions && hasNotNullAnnotations(newClassesCache, dependencyCache.getSymbolTable(), newClassQName, project);
if (haveToInstrument) {
try {
@@ -913,17 +914,19 @@ public class BackendCompilerWrapper {
}
}
private static boolean hasNotNullAnnotations(final Cache cache, final SymbolTable symbolTable, final int className) throws CacheCorruptedException {
private static boolean hasNotNullAnnotations(final Cache cache, final SymbolTable symbolTable, final int className, Project project) throws CacheCorruptedException {
final NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
final List<String> notNulls = manager.getNotNulls();
for (MethodInfo methodId : cache.getMethods(className)) {
for (AnnotationConstantValue annotation : methodId.getRuntimeInvisibleAnnotations()) {
if (AnnotationUtil.NOT_NULL.equals(symbolTable.getSymbol(annotation.getAnnotationQName()))) {
if (notNulls.contains(symbolTable.getSymbol(annotation.getAnnotationQName()))) {
return true;
}
}
final AnnotationConstantValue[][] paramAnnotations = methodId.getRuntimeInvisibleParameterAnnotations();
for (AnnotationConstantValue[] _singleParamAnnotations : paramAnnotations) {
for (AnnotationConstantValue annotation : _singleParamAnnotations) {
if (AnnotationUtil.NOT_NULL.equals(symbolTable.getSymbol(annotation.getAnnotationQName()))) {
if (notNulls.contains(symbolTable.getSymbol(annotation.getAnnotationQName()))) {
return true;
}
}
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.generation;
import com.intellij.CommonBundle;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
import com.intellij.ide.util.MemberChooser;
import com.intellij.openapi.diagnostic.Logger;
@@ -228,9 +229,9 @@ public class GenerateConstructorHandler extends GenerateMembersHandlerBase {
parmName = javaStyle.suggestUniqueVariableName(parmName, constructor, true);
PsiParameter parm = factory.createParameter(parmName, field.getType());
if (AnnotationUtil.isAnnotated(field, AnnotationUtil.NOT_NULL, false)) {
final PsiAnnotation annotation = factory.createAnnotationFromText("@" + AnnotationUtil.NOT_NULL, field);
final NullableNotNullManager nullableManager = NullableNotNullManager.getInstance(field.getProject());
if (nullableManager.isNotNull(field, false)) {
final PsiAnnotation annotation = factory.createAnnotationFromText("@" + nullableManager.getDefaultNotNull(), field);
parm.getModifierList().addAfter(annotation, null);
}
@@ -313,12 +313,13 @@ public class OverrideImplementUtil {
}
final Module module = ModuleUtil.findModuleForPsiElement(targetClass);
final GlobalSearchScope moduleScope = module != null ? GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module) : null;
final JavaPsiFacade facade = JavaPsiFacade.getInstance(targetClass.getProject());
final Project project = targetClass.getProject();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
for (OverrideImplementsAnnotationsHandler each : Extensions.getExtensions(OverrideImplementsAnnotationsHandler.EP_NAME)) {
for (String annotation : each.getAnnotations()) {
for (String annotation : each.getAnnotations(project)) {
if (moduleScope != null && facade.findClass(annotation, moduleScope) == null) continue;
if (AnnotationUtil.isAnnotated(overridden, annotation, false)) {
annotate(method, annotation, each.annotationsToRemove(annotation));
annotate(method, annotation, each.annotationsToRemove(project, annotation));
}
}
}
@@ -21,12 +21,13 @@
package com.intellij.codeInsight.generation;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
public interface OverrideImplementsAnnotationsHandler {
ExtensionPointName<OverrideImplementsAnnotationsHandler> EP_NAME = ExtensionPointName.create("com.intellij.overrideImplementsAnnotationsHandler");
String[] getAnnotations();
String[] getAnnotations(Project project);
@NotNull
String [] annotationsToRemove(@NotNull String fqName);
String [] annotationsToRemove(Project project, @NotNull String fqName);
}
@@ -21,23 +21,33 @@
package com.intellij.codeInsight.generation;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.JDOMExternalizableStringList;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
public class OverrideImplementsAnnotationsHandlerImpl implements OverrideImplementsAnnotationsHandler {
public String[] getAnnotations() {
return new String[]{AnnotationUtil.NOT_NULL,AnnotationUtil.NLS};
public String[] getAnnotations(Project project) {
final NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
final Collection<String> anns = new ArrayList<String>(manager.getNotNulls());
anns.add(AnnotationUtil.NLS);
return ArrayUtil.toStringArray(anns);
}
@NotNull
public String[] annotationsToRemove(@NotNull final String fqName) {
if (Comparing.strEqual(fqName, AnnotationUtil.NOT_NULL)) {
return new String[]{AnnotationUtil.NULLABLE};
public String[] annotationsToRemove(Project project, @NotNull final String fqName) {
final NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
if (manager.getNotNulls().contains(fqName)) {
return ArrayUtil.toStringArray(manager.getNullables());
}
if (Comparing.strEqual(fqName, AnnotationUtil.NLS)){
return new String[]{AnnotationUtil.NON_NLS};
}
return ArrayUtil.EMPTY_STRING_ARRAY;
}
}
}
@@ -23,13 +23,25 @@
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.psi.PsiModifierListOwner;
import com.intellij.util.ArrayUtil;
import java.util.List;
public class AddNotNullAnnotationFix extends AddNullableNotNullAnnotationFix {
@Deprecated
public AddNotNullAnnotationFix() {
super(AnnotationUtil.NOT_NULL, AnnotationUtil.NULLABLE);
}
public AddNotNullAnnotationFix(PsiModifierListOwner owner) {
super(AnnotationUtil.NOT_NULL, owner, AnnotationUtil.NULLABLE);
super(NullableNotNullManager.getInstance(owner.getProject()).getDefaultNotNull(),
owner,
getNullables(owner));
}
private static String[] getNullables(PsiModifierListOwner owner) {
final List<String> nullables = NullableNotNullManager.getInstance(owner.getProject()).getNullables();
return ArrayUtil.toStringArray(nullables);
}
}
@@ -23,9 +23,26 @@
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.psi.PsiModifierListOwner;
import com.intellij.util.ArrayUtil;
import java.util.List;
public class AddNullableAnnotationFix extends AddNullableNotNullAnnotationFix {
@Deprecated
public AddNullableAnnotationFix() {
super(AnnotationUtil.NULLABLE, AnnotationUtil.NOT_NULL);
}
}
public AddNullableAnnotationFix(PsiModifierListOwner owner) {
super(NullableNotNullManager.getInstance(owner.getProject()).getDefaultNullable(),
owner,
getNotNulls(owner));
}
private static String[] getNotNulls(PsiModifierListOwner owner) {
final List<String> notnulls = NullableNotNullManager.getInstance(owner.getProject()).getNotNulls();
return ArrayUtil.toStringArray(notnulls);
}
}
@@ -30,11 +30,11 @@ import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
public class AddNullableNotNullAnnotationFix extends AddAnnotationFix {
public AddNullableNotNullAnnotationFix(final String annotation, final String annotationToRemove) {
public AddNullableNotNullAnnotationFix(final String annotation, final String... annotationToRemove) {
super(annotation, annotationToRemove);
}
public AddNullableNotNullAnnotationFix(final String fqn, final PsiModifierListOwner owner, final String annotationToRemove) {
public AddNullableNotNullAnnotationFix(final String fqn, final PsiModifierListOwner owner, final String... annotationToRemove) {
super(fqn, owner, annotationToRemove);
}
@@ -54,4 +54,4 @@ public class AddNullableNotNullAnnotationFix extends AddAnnotationFix {
}
return true;
}
}
}
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -213,8 +214,9 @@ public class CreateFieldFromParameterAction implements IntentionAction {
modifierList.setModifierProperty(PsiModifier.STATIC, isMethodStatic);
modifierList.setModifierProperty(PsiModifier.FINAL, isFinal);
if (AnnotationUtil.isAnnotated(myParameter, AnnotationUtil.NULLABLE, false)) {
modifierList.addAfter(factory.createAnnotationFromText("@" + AnnotationUtil.NULLABLE, field), null);
final NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
if (manager.isNullable(myParameter, false)) {
modifierList.addAfter(factory.createAnnotationFromText("@" + manager.getDefaultNullable(), field), null);
}
PsiCodeBlock methodBody = method.getBody();
@@ -26,17 +26,24 @@ package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.NullableNotNullDialog;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.impl.quickfix.SimplifyBooleanExpressionFix;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.ex.BaseLocalInspectionTool;
import com.intellij.codeInspection.ex.EntryPointsManagerImpl;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NonNls;
@@ -47,6 +54,8 @@ import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;
@@ -266,7 +275,8 @@ public class DataFlowInspection extends BaseLocalInspectionTool {
final String text = isNullLiteralExpression(expr)
? InspectionsBundle.message("dataflow.message.return.null.from.notnullable")
: InspectionsBundle.message("dataflow.message.return.nullable.from.notnullable");
holder.registerProblem(expr, text, new AnnotateMethodFix(AnnotationUtil.NULLABLE, AnnotationUtil.NOT_NULL));
final NullableNotNullManager manager = NullableNotNullManager.getInstance(expr.getProject());
holder.registerProblem(expr, text, new AnnotateMethodFix(manager.getDefaultNullable(), ArrayUtil.toStringArray(manager.getNotNulls())));
}
}
@@ -416,10 +426,27 @@ public class DataFlowInspection extends BaseLocalInspectionTool {
}
});
gc.insets = new Insets(0, 0, 15, 0);
gc.insets = new Insets(0, 0, 0, 0);
gc.gridy = 0;
add(mySuggestNullables, gc);
final JButton configureAnnotations = new JButton("Configure annotations");
configureAnnotations.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Project project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(OptionsPanel.this));
if (project == null) project = ProjectManager.getInstance().getDefaultProject();
final NullableNotNullDialog dialog = new NullableNotNullDialog(project);
dialog.show();
}
});
gc.gridy++;
gc.fill = GridBagConstraints.NONE;
gc.insets.left = 20;
gc.insets.bottom = 15;
add(configureAnnotations, gc);
gc.insets.left = 0;
gc.gridy++;
add(myDontReportTrueAsserts, gc);
}
@@ -16,6 +16,7 @@
package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.value.*;
import com.intellij.psi.*;
@@ -45,7 +46,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
final PsiParameter[] params = callee.getParameterList().getParameters();
boolean[] result = new boolean[params.length];
for (int i = 0; i < params.length; i++) {
result[i] = AnnotationUtil.isAnnotated(params[i], AnnotationUtil.NOT_NULL, false);
result[i] = NullableNotNullManager.getInstance(params[i].getProject()).isNotNull(params[i], false);
}
return result;
}
@@ -85,7 +86,8 @@ public class StandardInstructionVisitor extends InstructionVisitor {
if (dfaDest instanceof DfaVariableValue) {
DfaVariableValue var = (DfaVariableValue) dfaDest;
final PsiVariable psiVariable = var.getPsiVariable();
if (AnnotationUtil.isAnnotated(psiVariable, AnnotationUtil.NOT_NULL, false)) {
final NullableNotNullManager nullableManager = NullableNotNullManager.getInstance(psiVariable.getProject());
if (nullableManager.isNotNull(psiVariable, false)) {
if (!memState.applyNotNull(dfaSource)) {
onAssigningToNotNullableVariable(instruction, runner);
}
@@ -19,6 +19,7 @@ import com.intellij.analysis.AnalysisScope;
import com.intellij.analysis.BaseAnalysisAction;
import com.intellij.analysis.BaseAnalysisActionDialog;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.quickfix.LocateLibraryDialog;
import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
@@ -87,7 +88,7 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
if (module != null && !processed.contains(module)) {
processed.add(module);
if (JavaPsiFacade.getInstance(project)
.findClass(AnnotationUtil.NULLABLE, GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)) == null) {
.findClass(NullableNotNullManager.getInstance(project).getDefaultNullable(), GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)) == null) {
modulesWithoutAnnotations.add(module);
}
if (PsiUtil.getLanguageLevel(file).compareTo(LanguageLevel.JDK_1_5) < 0) {
@@ -103,8 +104,9 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
return;
}
if (!modulesWithoutAnnotations.isEmpty()) {
if (Messages.showOkCancelDialog(project, "Infer Nullity Annotations requires that the JetBrains nullity annotations" +
" be available to your project.\n\nYou will need to add annotations.jar (available in your IDEA distribution) as a library. " +
if (Messages.showOkCancelDialog(project, "Infer Nullity Annotations requires that the nullity annotations" +
" be available to your project.\n\nYou will need to add annotations.jar as a library. " +
"It is possible to configure custom jar in e.g. Constant Conditions & Exceptions inspection or use JetBrains annotations available in installation. " +
" The IDEA nullity annotations are freely usable and redistributable under the Apache 2.0 license. Would you like to do it now?",
INFER_NULLITY_ANNOTATIONS, Messages.getErrorIcon()) == DialogWrapper.OK_EXIT_CODE) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@@ -16,6 +16,7 @@
package com.intellij.codeInspection.inferNullity;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.intention.AddAnnotationFix;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationDisplayType;
@@ -148,11 +149,12 @@ public class NullityInferrer {
}
public void apply(final Project project) {
final NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
for (SmartPsiElementPointer<? extends PsiModifierListOwner> pointer : myNullableSet) {
final PsiModifierListOwner element = pointer.getElement();
if (element != null) {
if (shouldIgnore(element)) continue;
new AddAnnotationFix(AnnotationUtil.NULLABLE, element, AnnotationUtil.NOT_NULL).invoke(project, null, element.getContainingFile());
new AddAnnotationFix(manager.getDefaultNullable(), element, manager.getDefaultNotNull()).invoke(project, null, element.getContainingFile());
}
}
@@ -160,7 +162,8 @@ public class NullityInferrer {
final PsiModifierListOwner element = pointer.getElement();
if (element != null) {
if (shouldIgnore(element)) continue;
new AddAnnotationFix(AnnotationUtil.NOT_NULL, element, AnnotationUtil.NULLABLE).invoke(project, null, element.getContainingFile());
new AddAnnotationFix(manager.getDefaultNotNull(), element, manager.getDefaultNullable()).invoke(project, null,
element.getContainingFile());
}
}
@@ -425,8 +428,8 @@ public class NullityInferrer {
return;
}
}
if (!AnnotationUtil.isAnnotated(method, AnnotationUtil.NOT_NULL, false) &&
AnnotationUtil.isAnnotated(method, AnnotationUtil.NOT_NULL, true)) {
final NullableNotNullManager manager = NullableNotNullManager.getInstance(method.getProject());
if (!manager.isNotNull(method, false) && manager.isNotNull(method, true)) {
registerNotNullAnnotation(method);
return;
}
@@ -16,12 +16,14 @@
package com.intellij.codeInspection.nullable;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.intention.AddAnnotationFix;
import com.intellij.codeInsight.intention.impl.AddNotNullAnnotationFix;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.BaseLocalInspectionTool;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
@@ -30,6 +32,7 @@ import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
import com.intellij.util.Query;
import org.jetbrains.annotations.NotNull;
@@ -48,18 +51,6 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
@SuppressWarnings({"WeakerAccess"}) public boolean REPORT_NOT_ANNOTATED_GETTER = true;
@SuppressWarnings({"WeakerAccess"}) public boolean REPORT_NOT_ANNOTATED_SETTER_PARAMETER = true;
@SuppressWarnings({"WeakerAccess"}) public boolean REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS = true;
private static final AnnotateMethodFix ANNOTATE_OVERRIDDEN_METHODS_FIX = new AnnotateMethodFix(AnnotationUtil.NOT_NULL, AnnotationUtil.NULLABLE){
protected boolean annotateOverriddenMethods() {
return true;
}
@NotNull
public String getName() {
return InspectionsBundle.message("annotate.overridden.methods.as.notnull");
}
};
private static final AnnotateOverriddenMethodParameterFix ANNOTATE_OVERRIDDEN_METHODS_PARAMS_FIX =
new AnnotateOverriddenMethodParameterFix(AnnotationUtil.NOT_NULL, AnnotationUtil.NULLABLE);
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
@@ -79,31 +70,34 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
if (TypeConversionUtil.isPrimitiveAndNotNull(type)) {
return;
}
final NullableNotNullManager manager = NullableNotNullManager.getInstance(field.getProject());
if (annotated.isDeclaredNotNull ^ annotated.isDeclaredNullable) {
final String anno = annotated.isDeclaredNotNull ? AnnotationUtil.NOT_NULL : AnnotationUtil.NULLABLE;
final String annoToRemove = annotated.isDeclaredNotNull ? AnnotationUtil.NULLABLE : AnnotationUtil.NOT_NULL;
final String simpleName = annotated.isDeclaredNotNull ? AnnotationUtil.NOT_NULL_SIMPLE_NAME : AnnotationUtil.NULLABLE_SIMPLE_NAME;
final String anno = annotated.isDeclaredNotNull ? manager.getDefaultNotNull() : manager.getDefaultNullable();
final List<String> annoToRemove = annotated.isDeclaredNotNull ? manager.getNullables() : manager.getNotNulls();
final String propName = JavaCodeStyleManager.getInstance(field.getProject()).variableNameToPropertyName(field.getName(), VariableKind.FIELD);
final String propName = JavaCodeStyleManager.getInstance(field.getProject()).variableNameToPropertyName(field.getName(),
VariableKind.FIELD);
final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
final PsiMethod getter = PropertyUtil.findPropertyGetter(field.getContainingClass(), propName, isStatic, false);
final String nullableSimpleName = StringUtil.getShortName(manager.getDefaultNullable());
final String notNullSimpleName = StringUtil.getShortName(manager.getDefaultNotNull());
if (getter != null) {
if (REPORT_NOT_ANNOTATED_GETTER) {
if (!AnnotationUtil.isAnnotated(getter, AnnotationUtil.ALL_ANNOTATIONS) &&
if (!AnnotationUtil.isAnnotated(getter, manager.getAllAnnotations()) &&
!TypeConversionUtil.isPrimitiveAndNotNull(getter.getReturnType())) {
holder.registerProblem(getter.getNameIdentifier(), InspectionsBundle
.message("inspection.nullable.problems.annotated.field.getter.not.annotated", simpleName),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AnnotateMethodFix(anno, annoToRemove));
.message("inspection.nullable.problems.annotated.field.getter.not.annotated", StringUtil.getShortName(anno)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AnnotateMethodFix(anno, ArrayUtil.toStringArray(annoToRemove)));
}
}
if (annotated.isDeclaredNotNull && AnnotationUtil.isAnnotated(getter, AnnotationUtil.NULLABLE, false)) {
if (annotated.isDeclaredNotNull && manager.isNullable(getter, false)) {
holder.registerProblem(getter.getNameIdentifier(), InspectionsBundle.message(
"inspection.nullable.problems.annotated.field.getter.conflict", simpleName, AnnotationUtil.NULLABLE_SIMPLE_NAME),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AnnotateMethodFix(anno, annoToRemove));
} else if (annotated.isDeclaredNullable && AnnotationUtil.isAnnotated(getter, AnnotationUtil.NOT_NULL, false)) {
"inspection.nullable.problems.annotated.field.getter.conflict", StringUtil.getShortName(anno), nullableSimpleName),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AnnotateMethodFix(anno, ArrayUtil.toStringArray(annoToRemove)));
} else if (annotated.isDeclaredNullable && manager.isNotNull(getter, false)) {
holder.registerProblem(getter.getNameIdentifier(), InspectionsBundle.message(
"inspection.nullable.problems.annotated.field.getter.conflict", simpleName, AnnotationUtil.NOT_NULL_SIMPLE_NAME),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AnnotateMethodFix(anno, annoToRemove));
"inspection.nullable.problems.annotated.field.getter.conflict", StringUtil.getShortName(anno), notNullSimpleName),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AnnotateMethodFix(anno, ArrayUtil.toStringArray(annoToRemove)));
}
}
@@ -113,22 +107,24 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
final PsiParameter[] parameters = setter.getParameterList().getParameters();
assert parameters.length == 1;
final PsiParameter parameter = parameters[0];
if (REPORT_NOT_ANNOTATED_SETTER_PARAMETER && !AnnotationUtil.isAnnotated(parameter, AnnotationUtil.ALL_ANNOTATIONS) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) {
if (REPORT_NOT_ANNOTATED_SETTER_PARAMETER && !AnnotationUtil.isAnnotated(parameter, manager.getAllAnnotations()) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) {
holder.registerProblem(parameter.getNameIdentifier(),
InspectionsBundle.message("inspection.nullable.problems.annotated.field.setter.parameter.not.annotated", simpleName),
InspectionsBundle.message("inspection.nullable.problems.annotated.field.setter.parameter.not.annotated",
StringUtil.getShortName(anno)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new AddAnnotationFix(anno, parameter, annoToRemove));
new AddAnnotationFix(anno, parameter, ArrayUtil.toStringArray(annoToRemove)));
}
if (annotated.isDeclaredNotNull && AnnotationUtil.isAnnotated(parameter, AnnotationUtil.NULLABLE, false)) {
if (annotated.isDeclaredNotNull && manager.isNullable(parameter, false)) {
holder.registerProblem(parameter.getNameIdentifier(), InspectionsBundle.message(
"inspection.nullable.problems.annotated.field.setter.parameter.conflict", simpleName, AnnotationUtil.NULLABLE_SIMPLE_NAME),
"inspection.nullable.problems.annotated.field.setter.parameter.conflict",
StringUtil.getShortName(anno), nullableSimpleName),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new AddAnnotationFix(anno, parameter, annoToRemove));
} else if (annotated.isDeclaredNullable && AnnotationUtil.isAnnotated(parameter, AnnotationUtil.NOT_NULL, false)) {
new AddAnnotationFix(anno, parameter, ArrayUtil.toStringArray(annoToRemove)));
} else if (annotated.isDeclaredNullable && manager.isNotNull(parameter, false)) {
holder.registerProblem(parameter.getNameIdentifier(), InspectionsBundle.message(
"inspection.nullable.problems.annotated.field.setter.parameter.conflict", simpleName, AnnotationUtil.NOT_NULL_SIMPLE_NAME),
"inspection.nullable.problems.annotated.field.setter.parameter.conflict", StringUtil.getShortName(anno), notNullSimpleName),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new AddAnnotationFix(anno, parameter, annoToRemove));
new AddAnnotationFix(anno, parameter, ArrayUtil.toStringArray(annoToRemove)));
}
if (containingClass == null) {
return;
@@ -164,22 +160,25 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
if (!method.equals(parameter.getDeclarationScope())) {
return true;
}
if (REPORT_NOT_ANNOTATED_SETTER_PARAMETER && !AnnotationUtil.isAnnotated(parameter, AnnotationUtil.ALL_ANNOTATIONS)) {
if (REPORT_NOT_ANNOTATED_SETTER_PARAMETER && !AnnotationUtil.isAnnotated(parameter, manager.getAllAnnotations())) {
holder.registerProblem(parameter.getNameIdentifier(), InspectionsBundle
.message("inspection.nullable.problems.annotated.field.constructor.parameter.not.annotated", simpleName),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AddAnnotationFix(anno, parameter, annoToRemove));
.message("inspection.nullable.problems.annotated.field.constructor.parameter.not.annotated",
StringUtil.getShortName(anno)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AddAnnotationFix(anno, parameter, ArrayUtil.toStringArray(annoToRemove)));
return true;
}
if (annotated.isDeclaredNotNull && AnnotationUtil.isAnnotated(parameter, AnnotationUtil.NULLABLE, false)) {
if (annotated.isDeclaredNotNull && manager.isNullable(parameter, false)) {
holder.registerProblem(parameter.getNameIdentifier(), InspectionsBundle.message(
"inspection.nullable.problems.annotated.field.constructor.parameter.conflict", simpleName, AnnotationUtil.NULLABLE_SIMPLE_NAME),
"inspection.nullable.problems.annotated.field.constructor.parameter.conflict", StringUtil.getShortName(anno),
nullableSimpleName),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new AddAnnotationFix(anno, parameter, annoToRemove));
} else if (annotated.isDeclaredNullable && AnnotationUtil.isAnnotated(parameter, AnnotationUtil.NOT_NULL, false)) {
new AddAnnotationFix(anno, parameter, ArrayUtil.toStringArray(annoToRemove)));
} else if (annotated.isDeclaredNullable && manager.isNotNull(parameter, false)) {
holder.registerProblem(parameter.getNameIdentifier(), InspectionsBundle.message(
"inspection.nullable.problems.annotated.field.constructor.parameter.conflict", simpleName, AnnotationUtil.NOT_NULL_SIMPLE_NAME),
"inspection.nullable.problems.annotated.field.constructor.parameter.conflict", StringUtil.getShortName(anno),
notNullSimpleName),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new AddAnnotationFix(anno, parameter, annoToRemove));
new AddAnnotationFix(anno, parameter, ArrayUtil.toStringArray(annoToRemove)));
}
return true;
}
@@ -217,8 +216,9 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
}
}
private static Annotated check(final PsiModifierListOwner parameter, final ProblemsHolder holder, PsiType type) {
PsiAnnotation isDeclaredNotNull = AnnotationUtil.findAnnotation(parameter, AnnotationUtil.NOT_NULL);
PsiAnnotation isDeclaredNullable = AnnotationUtil.findAnnotation(parameter, AnnotationUtil.NULLABLE);
final NullableNotNullManager manager = NullableNotNullManager.getInstance(parameter.getProject());
PsiAnnotation isDeclaredNotNull = AnnotationUtil.findAnnotation(parameter, manager.getNotNulls());
PsiAnnotation isDeclaredNullable = AnnotationUtil.findAnnotation(parameter, manager.getNullables());
if (isDeclaredNullable != null && isDeclaredNotNull != null) {
reportNullableNotNullConflict(holder, parameter, isDeclaredNullable, isDeclaredNotNull);
}
@@ -262,6 +262,7 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
boolean[] reported_notnull_parameter_overrides_nullable = new boolean[parameters.length];
boolean[] reported_not_annotated_parameter_overrides_notnull = new boolean[parameters.length];
final NullableNotNullManager nullableManager = NullableNotNullManager.getInstance(holder.getProject());
for (MethodSignatureBackedByPsiMethod superMethodSignature : superMethodSignatures) {
PsiMethod superMethod = superMethodSignature.getMethod();
if (!reported_nullable_method_overrides_notnull
@@ -281,11 +282,12 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
reported_not_annotated_method_overrides_notnull = true;
holder.registerProblem(method.getNameIdentifier(),
InspectionsBundle.message("inspection.nullable.problems.method.overrides.NotNull"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AnnotateMethodFix(AnnotationUtil.NOT_NULL, AnnotationUtil.NULLABLE) {
public int annotateBaseMethod(final PsiMethod method, final PsiMethod superMethod, final Project project) {
return NullableStuffInspection.this.annotateBaseMethod(method, superMethod, project);
}
});
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AnnotateMethodFix(
nullableManager.getDefaultNotNull(), ArrayUtil.toStringArray(nullableManager.getNullables())) {
public int annotateBaseMethod(final PsiMethod method, final PsiMethod superMethod, final Project project) {
return NullableStuffInspection.this.annotateBaseMethod(method, superMethod, project);
}
});
}
if (REPORT_NOTNULL_PARAMETER_OVERRIDES_NULLABLE || REPORT_NOT_ANNOTATED_PARAMETER_OVERRIDES_NOTNULL) {
PsiParameter[] superParameters = superMethod.getParameterList().getParameters();
@@ -296,21 +298,22 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
PsiParameter parameter = parameters[i];
PsiParameter superParameter = superParameters[i];
if (!reported_notnull_parameter_overrides_nullable[i] && REPORT_NOTNULL_PARAMETER_OVERRIDES_NULLABLE &&
AnnotationUtil.isAnnotated(parameter, AnnotationUtil.NOT_NULL, false) &&
AnnotationUtil.isAnnotated(superParameter, AnnotationUtil.NULLABLE, false)) {
nullableManager.isNotNull(parameter, false) &&
nullableManager.isNullable(superParameter, false)) {
reported_notnull_parameter_overrides_nullable[i] = true;
holder.registerProblem(parameter.getNameIdentifier(),
InspectionsBundle.message("inspection.nullable.problems.NotNull.parameter.overrides.Nullable"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
if (!reported_not_annotated_parameter_overrides_notnull[i] && REPORT_NOT_ANNOTATED_PARAMETER_OVERRIDES_NOTNULL &&
!AnnotationUtil.isAnnotated(parameter, AnnotationUtil.ALL_ANNOTATIONS) &&
AnnotationUtil.isAnnotated(superParameter, AnnotationUtil.NOT_NULL, false)) {
reported_not_annotated_parameter_overrides_notnull[i] = true;
holder.registerProblem(parameter.getNameIdentifier(),
InspectionsBundle.message("inspection.nullable.problems.parameter.overrides.NotNull"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new AddNotNullAnnotationFix(parameter));
if (!reported_not_annotated_parameter_overrides_notnull[i] && REPORT_NOT_ANNOTATED_PARAMETER_OVERRIDES_NOTNULL) {
if (!AnnotationUtil.isAnnotated(parameter, nullableManager.getAllAnnotations()) &&
nullableManager.isNotNull(superParameter, false)) {
reported_not_annotated_parameter_overrides_notnull[i] = true;
holder.registerProblem(parameter.getNameIdentifier(),
InspectionsBundle.message("inspection.nullable.problems.parameter.overrides.NotNull"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new AddNotNullAnnotationFix(parameter));
}
}
}
}
@@ -322,7 +325,7 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
boolean hasAnnotatedParameter = false;
for (int i = 0; i < parameters.length; i++) {
PsiParameter parameter = parameters[i];
parameterAnnotated[i] = AnnotationUtil.isAnnotated(parameter, AnnotationUtil.NOT_NULL, false);
parameterAnnotated[i] = nullableManager.isNotNull(parameter, false);
hasAnnotatedParameter |= parameterAnnotated[i];
}
if (hasAnnotatedParameter || annotated.isDeclaredNotNull) {
@@ -334,11 +337,20 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
if (!manager.isInProject(overriding)) continue;
if (!methodQuickFixSuggested
&& annotated.isDeclaredNotNull
&& !AnnotationUtil.isAnnotated(overriding, AnnotationUtil.NOT_NULL, false)) {
&& !nullableManager.isNotNull(overriding, false)) {
method.getNameIdentifier(); //load tree
PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, AnnotationUtil.NOT_NULL);
PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, nullableManager.getNotNulls());
holder.registerProblem(annotation, InspectionsBundle.message("nullable.stuff.problems.overridden.methods.are.not.annotated"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, ANNOTATE_OVERRIDDEN_METHODS_FIX);
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AnnotateMethodFix(nullableManager.getDefaultNotNull(), ArrayUtil.toStringArray(nullableManager.getNullables())){
protected boolean annotateOverriddenMethods() {
return true;
}
@NotNull
public String getName() {
return InspectionsBundle.message("annotate.overridden.methods.as.notnull");
}
});
methodQuickFixSuggested = true;
}
if (hasAnnotatedParameter) {
@@ -346,12 +358,13 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
for (int i = 0; i < psiParameters.length; i++) {
if (parameterQuickFixSuggested[i]) continue;
PsiParameter parameter = psiParameters[i];
if (parameterAnnotated[i] && !AnnotationUtil.isAnnotated(parameter, AnnotationUtil.NOT_NULL, false)) {
if (parameterAnnotated[i] && !nullableManager.isNotNull(parameter, false)) {
parameters[i].getNameIdentifier(); //be sure that corresponding tree element available
PsiAnnotation annotation = AnnotationUtil.findAnnotation(parameters[i], AnnotationUtil.NOT_NULL);
PsiAnnotation annotation = AnnotationUtil.findAnnotation(parameters[i], nullableManager.getNotNulls());
holder.registerProblem(annotation,
InspectionsBundle.message("nullable.stuff.problems.overridden.method.parameters.are.not.annotated"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, ANNOTATE_OVERRIDDEN_METHODS_PARAMS_FIX);
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new AnnotateOverriddenMethodParameterFix(nullableManager.getDefaultNotNull(), nullableManager.getDefaultNullable()));
parameterQuickFixSuggested[i] = true;
}
}
@@ -362,7 +375,8 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
}
protected int annotateBaseMethod(final PsiMethod method, final PsiMethod superMethod, final Project project) {
return new AnnotateMethodFix(AnnotationUtil.NOT_NULL, AnnotationUtil.NULLABLE).annotateBaseMethod(method, superMethod, project);
final NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
return new AnnotateMethodFix(manager.getDefaultNotNull(), ArrayUtil.toStringArray(manager.getNullables())).annotateBaseMethod(method, superMethod, project);
}
private static void reportNullableNotNullConflict(final ProblemsHolder holder, final PsiModifierListOwner listOwner, final PsiAnnotation declaredNullable,
@@ -18,7 +18,9 @@ package com.intellij.refactoring.extractMethod;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.ChangeContextUtil;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInsight.intention.impl.AddNullableAnnotationFix;
import com.intellij.codeInsight.intention.impl.AddNullableNotNullAnnotationFix;
import com.intellij.codeInspection.dataFlow.RunnerResult;
import com.intellij.codeInspection.dataFlow.StandardDataFlowRunner;
@@ -957,11 +959,11 @@ public class ExtractMethodProcessor implements MatchProvider {
if (myNullConditionalCheck) {
final boolean isNullCheckReturnNull = (myHasExpressionOutput ? 1 : 0) + (myGenerateConditionalExit ? 1 : 0) + myOutputVariables.length <= 1;
if (isNullCheckReturnNull && PsiUtil.isLanguageLevel5OrHigher(myElements[0])) {
final NullableNotNullManager manager = NullableNotNullManager.getInstance(myProject);
final PsiClass nullableAnnotationClass =
JavaPsiFacade.getInstance(myProject).findClass(AnnotationUtil.NULLABLE, GlobalSearchScope.allScope(myProject));
JavaPsiFacade.getInstance(myProject).findClass(manager.getDefaultNullable(), GlobalSearchScope.allScope(myProject));
if (nullableAnnotationClass != null) {
new AddNullableNotNullAnnotationFix(AnnotationUtil.NULLABLE, newMethod, AnnotationUtil.NOT_NULL)
.invoke(myProject, myEditor, myTargetClass.getContainingFile());
new AddNullableAnnotationFix(newMethod).invoke(myProject, myEditor, myTargetClass.getContainingFile());
}
}
}
@@ -21,6 +21,7 @@
package com.intellij.refactoring.extractMethodObject;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -524,8 +525,9 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
final PsiModifierList modifierList = field.getModifierList();
LOG.assertTrue(modifierList != null);
if (AnnotationUtil.isAnnotated(parameter, AnnotationUtil.NULLABLE, false)) {
modifierList.addAfter(myElementFactory.createAnnotationFromText("@" + AnnotationUtil.NULLABLE, field), null);
final NullableNotNullManager manager = NullableNotNullManager.getInstance(myProject);
if (manager.isNullable(parameter, false)) {
modifierList.addAfter(myElementFactory.createAnnotationFromText("@" + manager.getDefaultNullable(), field), null);
}
modifierList.setModifierProperty(PsiModifier.FINAL, isFinal);
@@ -16,6 +16,7 @@
package com.intellij.refactoring.inheritanceToDelegation;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.find.findUsages.PsiElement2UsageTargetAdapter;
import com.intellij.openapi.diagnostic.Logger;
@@ -522,12 +523,13 @@ public class InheritanceToDelegationProcessor extends BaseRefactoringProcessor {
PsiMethod methodToAdd = GenerateMembersUtil.substituteGenericMethod(method, substitutor);
final PsiModifierList modifierList = methodToAdd.getModifierList();
final NullableNotNullManager manager = NullableNotNullManager.getInstance(myProject);
modifierList.setModifierProperty(PsiModifier.ABSTRACT, false);
if (AnnotationUtil.isAnnotated(method, AnnotationUtil.NULLABLE, false)) {
modifierList.addAfter(myFactory.createAnnotationFromText("@" + AnnotationUtil.NULLABLE, methodToAdd), null);
if (manager.isNullable(method, false)) {
modifierList.addAfter(myFactory.createAnnotationFromText("@" + manager.getDefaultNullable(), methodToAdd), null);
}
else if (AnnotationUtil.isAnnotated(method, AnnotationUtil.NOT_NULL, false)) {
modifierList.addAfter(myFactory.createAnnotationFromText("@" + AnnotationUtil.NOT_NULL, methodToAdd), null);
else if (manager.isNotNull(method, false)) {
modifierList.addAfter(myFactory.createAnnotationFromText("@" + manager.getDefaultNotNull(), methodToAdd), null);
}
final String delegationBody = getDelegationBody(methodToAdd, delegationTarget);
@@ -76,11 +76,11 @@ public class AnnotationUtil {
}
public static boolean isNullable(@NotNull PsiModifierListOwner owner) {
return !isNotNull(owner) && isAnnotated(owner, NULLABLE, true);
return !isNotNull(owner) && NullableNotNullManager.getInstance(owner.getProject()).isNullable(owner, true);
}
public static boolean isNotNull(@NotNull PsiModifierListOwner owner) {
return isAnnotated(owner, NOT_NULL, true);
return NullableNotNullManager.getInstance(owner.getProject()).isNotNull(owner, true);
}
@Nullable
@@ -198,8 +198,14 @@ public class AnnotationUtil {
}
public static boolean isAnnotated(PsiModifierListOwner listOwner, Collection<String> annotations) {
return isAnnotated(listOwner, annotations, false);
}
public static boolean isAnnotated(PsiModifierListOwner listOwner,
Collection<String> annotations,
final boolean checkHierarchy) {
for (String annotation : annotations) {
if (isAnnotated(listOwner, annotation, false)) return true;
if (isAnnotated(listOwner, annotation, checkHierarchy)) return true;
}
return false;
}
@@ -0,0 +1,186 @@
/*
* Copyright 2000-2011 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 com.intellij.codeInsight;
import com.intellij.ide.ui.ListCellRendererWrapper;
import com.intellij.ide.util.ClassFilter;
import com.intellij.ide.util.TreeClassChooser;
import com.intellij.ide.util.TreeClassChooserFactory;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.IconLoader;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.ui.LayeredIcon;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.components.JBList;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Icons;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* User: anna
* Date: 1/25/11
*/
public class NullableNotNullDialog extends DialogWrapper {
@NonNls private static final String GENERAL_ADD_ICON_PATH = "/general/add.png";
private static final Icon ADD_ICON = IconLoader.getIcon(GENERAL_ADD_ICON_PATH);
private static final Icon REMOVE_ICON = IconLoader.getIcon("/general/remove.png");
private static final Icon SAVE_ICON = IconLoader.getIcon("/ide/defaultProfile.png");
private final Project myProject;
private AnnoPanel myNullablePanel;
private AnnoPanel myNotNullPanel;
public NullableNotNullDialog(Project project) {
super(project, true);
myProject = project;
init();
setTitle("Nullable/NotNull configuration");
}
@Override
protected JComponent createCenterPanel() {
final JPanel panel = new JPanel(new VerticalFlowLayout());
final NullableNotNullManager manager = NullableNotNullManager.getInstance(myProject);
myNullablePanel =
new AnnoPanel("Nullable", manager.getDefaultNullable(), manager.getNullables(), NullableNotNullManager.DEFAULT_NULLABLES);
panel.add(myNullablePanel);
myNotNullPanel = new AnnoPanel("NotNull", manager.getDefaultNotNull(), manager.getNotNulls(), NullableNotNullManager.DEFAULT_NOT_NULLS);
panel.add(myNotNullPanel);
return panel;
}
@Override
protected void doOKAction() {
final NullableNotNullManager manager = NullableNotNullManager.getInstance(myProject);
manager.setNotNulls(myNotNullPanel.getAnns());
manager.setDefaultNotNull(myNotNullPanel.getDefaultAnn());
manager.setNullables(myNullablePanel.getAnns());
manager.setDefaultNullable(myNullablePanel.getDefaultAnn());
super.doOKAction();
}
private class AnnoPanel extends JPanel {
private String myDefaultAnn;
private final String[] myDefaultAnns;
private final JBList myList;
private AnnoPanel(final String title, final String defaultAnn, final List<String> anns, final String[] defaultAnns) {
super(new BorderLayout());
myDefaultAnn = defaultAnn;
myDefaultAnns = defaultAnns;
setBorder(BorderFactory.createTitledBorder(title));
myList = new JBList(anns);
myList.setCellRenderer(new DefaultListCellRenderer(){
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
final Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (Comparing.strEqual((String)value, myDefaultAnn)) {
setIcon(Icons.ADVICE_ICON);
setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD));
}
else {
setIcon(EmptyIcon.ICON_16);
}
setText((String)value);
return component;
}
});
myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myList.setSelectedValue(defaultAnn, true);
add(ScrollPaneFactory.createScrollPane(myList), BorderLayout.CENTER);
final DefaultActionGroup group = new DefaultActionGroup();
group.add(new AnAction("Add", "Add", ADD_ICON) {
{
registerCustomShortcutSet(CommonShortcuts.INSERT, myList);
}
@Override
public void actionPerformed(AnActionEvent e) {
chooseAnnotation(title, myList, null);
}
});
group.add(new AnAction("Delete", "Delete", REMOVE_ICON) {
{
registerCustomShortcutSet(CommonShortcuts.DELETE, myList);
}
@Override
public void update(AnActionEvent e) {
final Object selectedValue = myList.getSelectedValue();
e.getPresentation().setEnabled(ArrayUtil.find(myDefaultAnns, selectedValue) == -1);
}
@Override
public void actionPerformed(AnActionEvent e) {
((DefaultListModel)myList.getModel()).removeElement(myList.getSelectedValue());
}
});
group.add(new AnAction("Make default", "Default", SAVE_ICON) {
@Override
public void update(AnActionEvent e) {
e.getPresentation().setEnabled(!Comparing.strEqual(myDefaultAnn, (String)myList.getSelectedValue()));
}
@Override
public void actionPerformed(AnActionEvent e) {
myDefaultAnn = (String)myList.getSelectedValue();
}
});
add(ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent(), BorderLayout.NORTH);
}
private void chooseAnnotation(String title, JBList list, PsiClass initial) {
final TreeClassChooser chooser = TreeClassChooserFactory.getInstance(myProject)
.createNoInnerClassesScopeChooser("Choose " + title, GlobalSearchScope.allScope(myProject), new ClassFilter() {
@Override
public boolean isAccepted(PsiClass aClass) {
return aClass.isAnnotationType();
}
}, initial);
chooser.showDialog();
final PsiClass selected = chooser.getSelected();
if (selected != null) {
final String qualifiedName = selected.getQualifiedName();
((DefaultListModel)list.getModel()).addElement(qualifiedName);
}
}
public String getDefaultAnn() {
return myDefaultAnn;
}
public Object[] getAnns() {
return ((DefaultListModel)myList.getModel()).toArray();
}
}
}
@@ -0,0 +1,141 @@
/*
* Copyright 2000-2011 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 com.intellij.codeInsight;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.psi.PsiModifierListOwner;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* User: anna
* Date: 1/25/11
*/
@State(
name = "NullableNotNullManager",
storages = {@Storage(id = "default", file = "$PROJECT_FILE$")}
)
public class NullableNotNullManager implements PersistentStateComponent<Element> {
private static final Logger LOG = Logger.getInstance("#" + NullableNotNullManager.class.getName());
public String myDefaultNullable = AnnotationUtil.NULLABLE;
public String myDefaultNotNull = AnnotationUtil.NOT_NULL;
public JDOMExternalizableStringList myNullables = new JDOMExternalizableStringList();
public JDOMExternalizableStringList myNotNulls = new JDOMExternalizableStringList();
public static final String[] DEFAULT_NULLABLES = {AnnotationUtil.NULLABLE, "javax.annotation.Nullable", "edu.umd.cs.findbugs.annotations.Nullable"};
public static final String[] DEFAULT_NOT_NULLS = {AnnotationUtil.NOT_NULL, "javax.annotation.Nonnull", "edu.umd.cs.findbugs.annotations.NonNull"};
public static NullableNotNullManager getInstance(Project project) {
return ServiceManager.getService(project, NullableNotNullManager.class);
}
public Collection<String> getAllAnnotations() {
final List<String> all = new ArrayList<String>(getNullables());
all.addAll(getNotNulls());
return all;
}
public void setNotNulls(Object[] anns) {
myNotNulls.clear();
for (Object ann : anns) {
myNotNulls.add((String)ann);
}
}
public void setNullables(Object[] anns) {
myNullables.clear();
for (Object ann : anns) {
myNullables.add((String)ann);
}
}
public String getDefaultNullable() {
return myDefaultNullable;
}
public void setDefaultNullable(@NotNull String defaultNullable) {
LOG.assertTrue(myNullables.contains(defaultNullable));
myDefaultNullable = defaultNullable;
}
public String getDefaultNotNull() {
return myDefaultNotNull;
}
public void setDefaultNotNull(@NotNull String defaultNotNull) {
LOG.assertTrue(myNotNulls.contains(defaultNotNull));
myDefaultNotNull = defaultNotNull;
}
public List<String> getNullables() {
if (myNullables.isEmpty()) {
Collections.addAll(myNullables, DEFAULT_NULLABLES);
}
return myNullables;
}
public boolean isNullable(PsiModifierListOwner owner, boolean checkBases) {
return AnnotationUtil.isAnnotated(owner, getNullables(), checkBases);
}
public boolean isNotNull(PsiModifierListOwner owner, boolean checkBases) {
return AnnotationUtil.isAnnotated(owner, getNotNulls(), checkBases);
}
public List<String> getNotNulls() {
if (myNotNulls.isEmpty()) {
Collections.addAll(myNotNulls, DEFAULT_NOT_NULLS);
}
return myNotNulls;
}
@Override
public Element getState() {
final Element component = new Element("component");
if (getNullables().size() == DEFAULT_NULLABLES.length && getNotNulls().size() == DEFAULT_NOT_NULLS.length) {
return component;
}
try {
DefaultJDOMExternalizer.writeExternal(this, component);
}
catch (WriteExternalException e) {
LOG.error(e);
}
return component;
}
@Override
public void loadState(Element state) {
try {
DefaultJDOMExternalizer.readExternal(this, state);
}
catch (InvalidDataException e) {
LOG.error(e);
}
}
}
@@ -16,6 +16,7 @@
package com.intellij.psi.util;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
@@ -474,11 +475,12 @@ public class PropertyUtil {
private static void annotateWithNullableStuff(final PsiModifierListOwner field, final PsiElementFactory factory, final PsiModifierListOwner listOwner)
throws IncorrectOperationException {
if (AnnotationUtil.isAnnotated(field, AnnotationUtil.NOT_NULL, false)) {
annotate(factory, listOwner, AnnotationUtil.NOT_NULL);
final NullableNotNullManager manager = NullableNotNullManager.getInstance(field.getProject());
if (manager.isNotNull(field, false)) {
annotate(factory, listOwner, manager.getDefaultNotNull());
}
else if (AnnotationUtil.isAnnotated(field, AnnotationUtil.NULLABLE, false)) {
annotate(factory, listOwner, AnnotationUtil.NULLABLE);
else if (manager.isNullable(field, false)) {
annotate(factory, listOwner, manager.getDefaultNullable());
}
}
@@ -16,9 +16,11 @@
package com.siyeh.ig.bugs;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInspection.AnnotateMethodFix;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -58,11 +60,13 @@ public class ReturnNullInspection extends BaseInspection {
@Nullable
protected InspectionGadgetsFix buildFix(Object... infos) {
if (!AnnotationUtil.isAnnotatingApplicable((PsiElement) infos[0])) {
final PsiElement elt = (PsiElement)infos[0];
if (!AnnotationUtil.isAnnotatingApplicable(elt)) {
return null;
}
return new DelegatingFix(new AnnotateMethodFix(
AnnotationUtil.NULLABLE, AnnotationUtil.NOT_NULL));
final NullableNotNullManager manager = NullableNotNullManager.getInstance(elt.getProject());
return new DelegatingFix(new AnnotateMethodFix(
manager.getDefaultNullable(), ArrayUtil.toStringArray(manager.getNotNulls())));
}
public JComponent createOptionsPanel() {
@@ -110,8 +114,7 @@ public class ReturnNullInspection extends BaseInspection {
return;
}
final boolean isArray = returnType.getArrayDimensions() > 0;
if (AnnotationUtil.isAnnotated(method, AnnotationUtil.NULLABLE,
false)) {
if (NullableNotNullManager.getInstance(method.getProject()).isNullable(method, false)) {
return;
}
if (m_reportCollectionMethods &&
@@ -124,4 +127,4 @@ public class ReturnNullInspection extends BaseInspection {
}
}
}
}
}
@@ -21,18 +21,19 @@
package com.theoryinpractice.testng.intention;
import com.intellij.codeInsight.generation.OverrideImplementsAnnotationsHandler;
import com.intellij.openapi.project.Project;
import com.intellij.util.ArrayUtil;
import com.theoryinpractice.testng.util.TestNGUtil;
import org.jetbrains.annotations.NotNull;
public class OverrideImplementsTestNGAnnotationsHandler implements OverrideImplementsAnnotationsHandler{
public String[] getAnnotations() {
public String[] getAnnotations(Project project) {
return TestNGUtil.CONFIG_ANNOTATIONS_FQN;
}
@NotNull
public String[] annotationsToRemove(@NotNull final String fqName) {
public String[] annotationsToRemove(Project project, @NotNull final String fqName) {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
}
@@ -1,8 +1,8 @@
<html>
<body>
<font face="verdana" size="-1">This inspection reports problems related to
<b><font color="#000080">@org.jetbrains.annotations.Nullable</font></b> and <b><font color="#000080">@org.jetbrains.annotations.NotNull</font></b>
annotations usage.
<b><font color="#000080">@Nullable</font></b> and <b><font color="#000080">@NotNull</font></b>
annotations usage configured in Constant conditions & exceptions inspection.
<br>
</font>
+3
View File
@@ -447,6 +447,9 @@
<projectService serviceInterface="com.intellij.codeInspection.ex.EntryPointsManagerImpl"
serviceImplementation="com.intellij.codeInspection.ex.EntryPointsManagerImpl"/>
<projectService serviceInterface="com.intellij.codeInsight.NullableNotNullManager"
serviceImplementation="com.intellij.codeInsight.NullableNotNullManager"/>
<projectService serviceInterface="com.intellij.compiler.impl.javaCompiler.javac.JavacConfiguration"
serviceImplementation="com.intellij.compiler.impl.javaCompiler.javac.JavacConfiguration"/>
<projectService serviceInterface="com.intellij.compiler.impl.javaCompiler.api.CompilerAPIConfiguration"