Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Bulenkov
2012-09-12 00:49:27 +04:00
54 changed files with 875 additions and 357 deletions
@@ -51,11 +51,12 @@ import java.util.*;
*/
public class GenericsHighlightUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil");
private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance();
private GenericsHighlightUtil() {
}
private GenericsHighlightUtil() { }
@Nullable
public static HighlightInfo checkInferredTypeArguments(PsiMethod genericMethod,
PsiMethodCallExpression call,
PsiSubstitutor substitutor) {
@@ -67,7 +68,8 @@ public class GenericsHighlightUtil {
PsiClassType[] extendsTypes = typeParameter.getExtendsListTypes();
for (PsiClassType type : extendsTypes) {
PsiType extendsType = substitutor.substitute(type);
if (substituted instanceof PsiWildcardType && TypeConversionUtil.erasure(extendsType).equals(TypeConversionUtil.erasure(((PsiWildcardType)substituted).getExtendsBound()))) {
if (substituted instanceof PsiWildcardType &&
TypeConversionUtil.erasure(extendsType).equals(TypeConversionUtil.erasure(((PsiWildcardType)substituted).getExtendsBound()))) {
PsiType extendsBound = ((PsiWildcardType)substituted).getExtendsBound();
if (extendsBound instanceof PsiClassType) {
PsiType[] parameters = ((PsiClassType)extendsBound).getParameters();
@@ -103,7 +105,7 @@ public class GenericsHighlightUtil {
}
@Nullable
public static HighlightInfo checkParameterizedReferenceTypeArguments(PsiElement resolved,
public static HighlightInfo checkParameterizedReferenceTypeArguments(final PsiElement resolved,
final PsiJavaCodeReferenceElement referenceElement,
final PsiSubstitutor substitutor) {
if (!(resolved instanceof PsiTypeParameterListOwner)) return null;
@@ -116,18 +118,14 @@ public class GenericsHighlightUtil {
final PsiReferenceParameterList referenceParameterList,
final PsiSubstitutor substitutor,
boolean registerIntentions) {
if (referenceParameterList != null) {
HighlightInfo info = HighlightUtil.checkGenericsFeature(referenceParameterList, referenceParameterList.getTypeParameterElements().length);
if (info != null) return info;
}
PsiDiamondType.DiamondInferenceResult inferenceResult = null;
PsiTypeElement[] referenceElements = null;
if (referenceParameterList != null) {
referenceElements = referenceParameterList.getTypeParameterElements();
if (referenceElements.length == 1 && referenceElements[0].getType() instanceof PsiDiamondType) {
if (!typeParameterListOwner.hasTypeParameters()) {
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceElements[0], "Diamond operator is not applicable for non-parameterized types");
final String description = JavaErrorMessages.message("generics.diamond.not.applicable");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceElements[0], description);
}
inferenceResult = ((PsiDiamondType)referenceElements[0].getType()).resolveInferredTypes();
final String errorMessage = inferenceResult.getErrorMessage();
@@ -165,9 +163,9 @@ public class GenericsHighlightUtil {
if (description != null) {
final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceParameterList, description);
if (registerIntentions) {
PsiElement pparent = referenceParameterList.getParent().getParent();
if (pparent instanceof PsiTypeElement) {
PsiElement variable = pparent.getParent();
PsiElement grandParent = referenceParameterList.getParent().getParent();
if (grandParent instanceof PsiTypeElement) {
PsiElement variable = grandParent.getParent();
if (variable instanceof PsiVariable) {
if (targetParametersNum == 0) {
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveTypeArgumentsFix(variable));
@@ -1029,7 +1027,7 @@ public class GenericsHighlightUtil {
MethodSignatureBackedByPsiMethod superMethod = SuperMethodsSearch.search(method, null, true, false).findFirst();
if (superMethod == null) {
HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, overrideAnnotation,
JavaErrorMessages.message("method.doesnot.override.super"));
JavaErrorMessages.message("method.does.not.override.super"));
PullAsAbstractUpFix.registerQuickFix(highlightInfo, method);
return highlightInfo;
}
@@ -1245,6 +1243,26 @@ public class GenericsHighlightUtil {
return list;
}
@Nullable
public static HighlightInfo checkParametersAllowed(PsiReferenceParameterList refParamList) {
HighlightInfo info = HighlightUtil.checkGenericsFeature(refParamList, refParamList.getTypeParameterElements().length);
if (info != null) return info;
if (refParamList.getTextLength() != 0) {
final PsiElement parent = refParamList.getParent();
if (parent instanceof PsiReferenceExpression) {
final PsiElement grandParent = parent.getParent();
if (!(grandParent instanceof PsiMethodCallExpression)) {
final String message = JavaErrorMessages.message("generics.reference.parameters.not.allowed");
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, refParamList, message);
}
}
}
return null;
}
@Nullable
public static HighlightInfo checkParametersOnRaw(PsiReferenceParameterList refParamList) {
if (refParamList.getTypeArguments().length == 0) return null;
JavaResolveResult resolveResult = null;
@@ -982,16 +982,17 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
@Override public void visitReferenceParameterList(PsiReferenceParameterList list) {
myHolder.add(GenericsHighlightUtil.checkParametersOnRaw(list));
@Override
public void visitReferenceParameterList(PsiReferenceParameterList list) {
myHolder.add(GenericsHighlightUtil.checkParametersAllowed(list));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParametersOnRaw(list));
}
@Override public void visitReturnStatement(PsiReturnStatement statement) {
try {
myHolder.add(HighlightUtil.checkReturnStatementType(statement));
}
catch (IndexNotReadyException ignore) {
}
catch (IndexNotReadyException ignore) { }
}
@Override public void visitStatement(PsiStatement statement) {
@@ -1526,15 +1526,16 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
return null;
}
boolean isCall = expression instanceof PsiMethodCallExpression;
PsiExpression qualifier = refExpr.getQualifierExpression();
if (qualifier == null) {
return myFactory.getVarFactory().createVariableValue(var, false, null);
return myFactory.getVarFactory().createVariableValue(var, false, null, isCall);
}
if (var instanceof PsiField && var.hasModifierProperty(PsiModifier.FINAL)) {
DfaVariableValue qualifierValue = createChainedVariableValue(qualifier);
if (qualifierValue != null) {
return myFactory.getVarFactory().createVariableValue(var, false, qualifierValue);
return myFactory.getVarFactory().createVariableValue(var, false, qualifierValue, isCall || qualifierValue.isViaMethods());
}
}
return null;
@@ -147,16 +147,13 @@ public class DataFlowInspection extends BaseLocalInspectionTool {
Pair<Set<Instruction>, Set<Instruction>> constConditions = runner.getConstConditionalExpressions();
Set<Instruction> trueSet = constConditions.getFirst();
Set<Instruction> falseSet = constConditions.getSecond();
Set<Instruction> npeSet = runner.getNPEInstructions();
Set<Instruction> cceSet = runner.getCCEInstructions();
Set<Instruction> redundantInstanceofs = StandardDataFlowRunner.getRedundantInstanceofs(runner, visitor);
ArrayList<Instruction> allProblems = new ArrayList<Instruction>();
allProblems.addAll(trueSet);
allProblems.addAll(falseSet);
allProblems.addAll(npeSet);
allProblems.addAll(cceSet);
allProblems.addAll(redundantInstanceofs);
allProblems.addAll(runner.getNPEInstructions());
allProblems.addAll(runner.getCCEInstructions());
allProblems.addAll(StandardDataFlowRunner.getRedundantInstanceofs(runner, visitor));
Collections.sort(allProblems, new Comparator<Instruction>() {
public int compare(Instruction i1, Instruction i2) {
@@ -168,82 +165,105 @@ public class DataFlowInspection extends BaseLocalInspectionTool {
for (Instruction instruction : allProblems) {
if (instruction instanceof MethodCallInstruction) {
MethodCallInstruction mcInstruction = (MethodCallInstruction)instruction;
if (mcInstruction.getCallExpression() instanceof PsiMethodCallExpression) {
PsiMethodCallExpression callExpression = (PsiMethodCallExpression)mcInstruction.getCallExpression();
LocalQuickFix[] fix = createNPEFixes(callExpression.getMethodExpression().getQualifierExpression(), callExpression);
holder.registerProblem(callExpression,
InspectionsBundle.message("dataflow.message.npe.method.invocation"),
fix);
}
reportCallMayProduceNpe(holder, (MethodCallInstruction)instruction);
}
else if (instruction instanceof FieldReferenceInstruction) {
FieldReferenceInstruction frInstruction = (FieldReferenceInstruction)instruction;
PsiElement elementToAssert = frInstruction.getElementToAssert();
PsiExpression expression = frInstruction.getExpression();
if (expression instanceof PsiArrayAccessExpression) {
LocalQuickFix[] fix = createNPEFixes((PsiExpression)elementToAssert, expression);
holder.registerProblem(expression,
InspectionsBundle.message("dataflow.message.npe.array.access"),
fix);
}
else {
LocalQuickFix[] fix = createNPEFixes((PsiExpression)elementToAssert, expression);
holder.registerProblem(elementToAssert,
InspectionsBundle.message("dataflow.message.npe.field.access"),
fix);
}
reportFieldAccessMayProduceNpe(holder, (FieldReferenceInstruction)instruction);
}
else if (instruction instanceof TypeCastInstruction) {
TypeCastInstruction tcInstruction = (TypeCastInstruction)instruction;
PsiTypeCastExpression typeCast = tcInstruction.getCastExpression();
holder.registerProblem(typeCast.getCastType(),
InspectionsBundle.message("dataflow.message.cce", typeCast.getOperand().getText()));
reportCastMayFail(holder, (TypeCastInstruction)instruction);
}
else if (instruction instanceof BranchingInstruction) {
PsiElement psiAnchor = ((BranchingInstruction)instruction).getPsiAnchor();
boolean underBinary = isAtRHSOfBooleanAnd(psiAnchor);
if (instruction instanceof InstanceofInstruction && visitor.isInstanceofRedundant((InstanceofInstruction)instruction)) {
if (visitor.canBeNull((BinopInstruction)instruction)) {
holder.registerProblem(psiAnchor,
InspectionsBundle.message("dataflow.message.redundant.instanceof"),
new RedundantInstanceofFix());
}
else {
final LocalQuickFix localQuickFix = createSimplifyBooleanExpressionFix(psiAnchor, true);
holder.registerProblem(psiAnchor,
InspectionsBundle.message(underBinary ? "dataflow.message.constant.condition.whenriched" : "dataflow.message.constant.condition", Boolean.toString(true)),
localQuickFix == null ? null : new LocalQuickFix[]{localQuickFix});
}
}
else if (psiAnchor instanceof PsiSwitchLabelStatement) {
if (falseSet.contains(instruction)) {
holder.registerProblem(psiAnchor,
InspectionsBundle.message("dataflow.message.unreachable.switch.label"));
}
}
else if (psiAnchor != null && !reportedAnchors.contains(psiAnchor) && !isCompileConstantInIfCondition(psiAnchor)) {
boolean evaluatesToTrue = trueSet.contains(instruction);
if (onTheLeftSideOfConditionalAssignemnt(psiAnchor)) {
holder.registerProblem(
psiAnchor,
InspectionsBundle.message("dataflow.message.pointless.assignment.expression", Boolean.toString(evaluatesToTrue)),
createSimplifyToAssignmentFix()
);
}
else if (shouldReportConditionAlwaysTrueOrFalse(psiAnchor, evaluatesToTrue)) {
final LocalQuickFix fix = createSimplifyBooleanExpressionFix(psiAnchor, evaluatesToTrue);
String message = InspectionsBundle.message(underBinary ?
"dataflow.message.constant.condition.whenriched" :
"dataflow.message.constant.condition", Boolean.toString(evaluatesToTrue));
holder.registerProblem(psiAnchor, message, fix == null ? null : new LocalQuickFix[]{fix});
}
reportedAnchors.add(psiAnchor);
}
handleBranchingInstruction(holder, visitor, trueSet, falseSet, reportedAnchors, (BranchingInstruction)instruction);
}
}
reportNullableArguments(runner, holder);
reportNullableAssignments(runner, holder);
reportUnboxedNullables(runner, holder);
reportNullableReturns(runner, holder);
}
private static void reportCallMayProduceNpe(ProblemsHolder holder, MethodCallInstruction mcInstruction) {
if (mcInstruction.getCallExpression() instanceof PsiMethodCallExpression) {
PsiMethodCallExpression callExpression = (PsiMethodCallExpression)mcInstruction.getCallExpression();
LocalQuickFix[] fix = createNPEFixes(callExpression.getMethodExpression().getQualifierExpression(), callExpression);
holder.registerProblem(callExpression,
InspectionsBundle.message("dataflow.message.npe.method.invocation"),
fix);
}
}
private static void reportFieldAccessMayProduceNpe(ProblemsHolder holder, FieldReferenceInstruction frInstruction) {
PsiElement elementToAssert = frInstruction.getElementToAssert();
PsiExpression expression = frInstruction.getExpression();
if (expression instanceof PsiArrayAccessExpression) {
LocalQuickFix[] fix = createNPEFixes((PsiExpression)elementToAssert, expression);
holder.registerProblem(expression,
InspectionsBundle.message("dataflow.message.npe.array.access"),
fix);
}
else {
LocalQuickFix[] fix = createNPEFixes((PsiExpression)elementToAssert, expression);
holder.registerProblem(elementToAssert,
InspectionsBundle.message("dataflow.message.npe.field.access"),
fix);
}
}
private static void reportCastMayFail(ProblemsHolder holder, TypeCastInstruction instruction) {
PsiTypeCastExpression typeCast = instruction.getCastExpression();
holder.registerProblem(typeCast.getCastType(),
InspectionsBundle.message("dataflow.message.cce", typeCast.getOperand().getText()));
}
private void handleBranchingInstruction(ProblemsHolder holder,
StandardInstructionVisitor visitor,
Set<Instruction> trueSet,
Set<Instruction> falseSet, HashSet<PsiElement> reportedAnchors, BranchingInstruction instruction) {
PsiElement psiAnchor = instruction.getPsiAnchor();
boolean underBinary = isAtRHSOfBooleanAnd(psiAnchor);
if (instruction instanceof InstanceofInstruction && visitor.isInstanceofRedundant((InstanceofInstruction)instruction)) {
if (visitor.canBeNull((BinopInstruction)instruction)) {
holder.registerProblem(psiAnchor,
InspectionsBundle.message("dataflow.message.redundant.instanceof"),
new RedundantInstanceofFix());
}
else {
final LocalQuickFix localQuickFix = createSimplifyBooleanExpressionFix(psiAnchor, true);
holder.registerProblem(psiAnchor,
InspectionsBundle.message(underBinary ? "dataflow.message.constant.condition.when.reached" : "dataflow.message.constant.condition", Boolean.toString(true)),
localQuickFix == null ? null : new LocalQuickFix[]{localQuickFix});
}
}
else if (psiAnchor instanceof PsiSwitchLabelStatement) {
if (falseSet.contains(instruction)) {
holder.registerProblem(psiAnchor,
InspectionsBundle.message("dataflow.message.unreachable.switch.label"));
}
}
else if (psiAnchor != null && !reportedAnchors.contains(psiAnchor) && !isCompileConstantInIfCondition(psiAnchor)) {
boolean evaluatesToTrue = trueSet.contains(instruction);
if (onTheLeftSideOfConditionalAssignemnt(psiAnchor)) {
holder.registerProblem(
psiAnchor,
InspectionsBundle.message("dataflow.message.pointless.assignment.expression", Boolean.toString(evaluatesToTrue)),
createSimplifyToAssignmentFix()
);
}
else if (shouldReportConditionAlwaysTrueOrFalse(psiAnchor, evaluatesToTrue) && !visitor.silenceConstantCondition(instruction)) {
final LocalQuickFix fix = createSimplifyBooleanExpressionFix(psiAnchor, evaluatesToTrue);
String message = InspectionsBundle.message(underBinary ?
"dataflow.message.constant.condition.when.reached" :
"dataflow.message.constant.condition", Boolean.toString(evaluatesToTrue));
holder.registerProblem(psiAnchor, message, fix == null ? null : new LocalQuickFix[]{fix});
}
reportedAnchors.add(psiAnchor);
}
}
private static void reportNullableArguments(StandardDataFlowRunner runner, ProblemsHolder holder) {
Set<PsiExpression> exprs = runner.getNullableArguments();
for (PsiExpression expr : exprs) {
final String text = isNullLiteralExpression(expr)
@@ -252,22 +272,25 @@ public class DataFlowInspection extends BaseLocalInspectionTool {
LocalQuickFix[] fixes = createNPEFixes(expr, expr);
holder.registerProblem(expr, text, fixes);
}
}
exprs = runner.getNullableAssignments();
for (PsiExpression expr : exprs) {
private static void reportNullableAssignments(StandardDataFlowRunner runner, ProblemsHolder holder) {
for (PsiExpression expr : runner.getNullableAssignments()) {
final String text = isNullLiteralExpression(expr)
? InspectionsBundle.message("dataflow.message.assigning.null")
: InspectionsBundle.message("dataflow.message.assigning.nullable");
holder.registerProblem(expr, text);
}
}
exprs = runner.getUnboxedNullables();
for (PsiExpression expr : exprs) {
private static void reportUnboxedNullables(StandardDataFlowRunner runner, ProblemsHolder holder) {
for (PsiExpression expr : runner.getUnboxedNullables()) {
holder.registerProblem(expr, InspectionsBundle.message("dataflow.message.unboxing"));
}
}
final Set<PsiReturnStatement> statements = runner.getNullableReturns();
for (PsiReturnStatement statement : statements) {
private static void reportNullableReturns(StandardDataFlowRunner runner, ProblemsHolder holder) {
for (PsiReturnStatement statement : runner.getNullableReturns()) {
final PsiExpression expr = statement.getReturnValue();
if (runner.isInNotNullMethod()) {
final String text = isNullLiteralExpression(expr)
@@ -36,6 +36,7 @@ import java.util.Set;
public class StandardInstructionVisitor extends InstructionVisitor {
private final Set<BinopInstruction> myReachable = new THashSet<BinopInstruction>();
private final Set<BinopInstruction> myCanBeNullInInstanceof = new THashSet<BinopInstruction>();
private final Set<BinopInstruction> myNotToReportReachability = new THashSet<BinopInstruction>();
private final Set<InstanceofInstruction> myUsefulInstanceofs = new THashSet<InstanceofInstruction>();
private final FactoryMap<MethodCallInstruction, boolean[]> myParametersNotNull = new FactoryMap<MethodCallInstruction, boolean[]>() {
@Override
@@ -298,7 +299,11 @@ public class StandardInstructionVisitor extends InstructionVisitor {
return null;
}
if (isViaMethods(dfaLeft) || isViaMethods(dfaRight)) {
myNotToReportReachability.add(instruction);
}
myCanBeNullInInstanceof.add(instruction);
ArrayList<DfaInstructionState> states = new ArrayList<DfaInstructionState>();
final DfaMemoryState trueCopy = memState.createCopy();
@@ -328,6 +333,10 @@ public class StandardInstructionVisitor extends InstructionVisitor {
return states.toArray(new DfaInstructionState[states.size()]);
}
private static boolean isViaMethods(DfaValue dfa) {
return dfa instanceof DfaVariableValue && ((DfaVariableValue)dfa).isViaMethods();
}
private void handleInstanceof(InstanceofInstruction instruction, DfaValue dfaRight, DfaValue dfaLeft) {
if ((dfaLeft instanceof DfaTypeValue || dfaLeft instanceof DfaNotNullValue) && dfaRight instanceof DfaTypeValue) {
final PsiType leftType;
@@ -397,4 +406,8 @@ public class StandardInstructionVisitor extends InstructionVisitor {
public boolean canBeNull(BinopInstruction instruction) {
return myCanBeNullInInstanceof.contains(instruction);
}
public boolean silenceConstantCondition(BranchingInstruction instruction) {
return instruction instanceof BinopInstruction && myNotToReportReachability.contains(instruction);
}
}
@@ -33,6 +33,7 @@ import java.util.ArrayList;
import java.util.List;
public class DfaVariableValue extends DfaValue {
public static class Factory {
private final DfaVariableValue mySharedInstance;
private final HashMap<String,ArrayList<DfaVariableValue>> myStringToObject;
@@ -46,12 +47,13 @@ public class DfaVariableValue extends DfaValue {
}
public DfaVariableValue createVariableValue(PsiVariable myVariable, boolean isNegated) {
return createVariableValue(myVariable, isNegated, null);
return createVariableValue(myVariable, isNegated, null, false);
}
public DfaVariableValue createVariableValue(PsiVariable myVariable, boolean isNegated, @Nullable DfaVariableValue qualifier) {
public DfaVariableValue createVariableValue(PsiVariable myVariable, boolean isNegated, @Nullable DfaVariableValue qualifier, boolean viaMethods) {
mySharedInstance.myVariable = myVariable;
mySharedInstance.myIsNegated = isNegated;
mySharedInstance.myQualifier = qualifier;
mySharedInstance.myViaMethods = viaMethods;
String id = mySharedInstance.toString();
ArrayList<DfaVariableValue> conditions = myStringToObject.get(id);
@@ -65,7 +67,7 @@ public class DfaVariableValue extends DfaValue {
}
}
DfaVariableValue result = new DfaVariableValue(myVariable, isNegated, myFactory, qualifier);
DfaVariableValue result = new DfaVariableValue(myVariable, isNegated, myFactory, qualifier, viaMethods);
if (qualifier != null) {
myQualifiersToChainedVariables.putValue(qualifier, result);
}
@@ -87,12 +89,14 @@ public class DfaVariableValue extends DfaValue {
private PsiVariable myVariable;
@Nullable private DfaVariableValue myQualifier;
private boolean myIsNegated;
private boolean myViaMethods;
private DfaVariableValue(PsiVariable variable, boolean isNegated, DfaValueFactory factory, @Nullable DfaVariableValue qualifier) {
private DfaVariableValue(PsiVariable variable, boolean isNegated, DfaValueFactory factory, @Nullable DfaVariableValue qualifier, boolean viaMethods) {
super(factory);
myVariable = variable;
myIsNegated = isNegated;
myQualifier = qualifier;
myViaMethods = viaMethods;
}
private DfaVariableValue(DfaValueFactory factory) {
@@ -111,7 +115,7 @@ public class DfaVariableValue extends DfaValue {
}
public DfaVariableValue createNegated() {
return myFactory.getVarFactory().createVariableValue(myVariable, !myIsNegated, myQualifier);
return myFactory.getVarFactory().createVariableValue(myVariable, !myIsNegated, myQualifier, myViaMethods);
}
@SuppressWarnings({"HardCodedStringLiteral"})
@@ -123,6 +127,7 @@ public class DfaVariableValue extends DfaValue {
private boolean hardEquals(DfaVariableValue aVar) {
return aVar.myVariable == myVariable &&
aVar.myIsNegated == myIsNegated &&
aVar.myViaMethods == myViaMethods &&
(myQualifier == null ? aVar.myQualifier == null : myQualifier.hardEquals(aVar.myQualifier));
}
@@ -130,4 +135,8 @@ public class DfaVariableValue extends DfaValue {
public DfaVariableValue getQualifier() {
return myQualifier;
}
public boolean isViaMethods() {
return myViaMethods;
}
}
@@ -17,21 +17,26 @@ package com.intellij.openapi.projectRoots;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
/**
* User: anna
* Date: 3/28/12
* @author anna
* @since 3/28/12
*/
public class JavaVersionServiceImpl extends JavaVersionService {
private JavaSdkVersion myTestVersion = null;
public void setTestVersion(JavaSdkVersion testVersion) {
@TestOnly
public void setTestVersion(@Nullable JavaSdkVersion testVersion) {
myTestVersion = testVersion;
}
@Override
public boolean isAtLeast(PsiElement element, JavaSdkVersion version) {
if (ApplicationManager.getApplication().isUnitTestMode()) return myTestVersion != null && myTestVersion.isAtLeast(version);
if (ApplicationManager.getApplication().isUnitTestMode()) {
return myTestVersion != null && myTestVersion.isAtLeast(version);
}
return JavaSdkVersionUtil.isAtLeast(element, version);
}
}
@@ -40,13 +40,14 @@ public class LocalsControlFlowPolicy implements ControlFlowPolicy {
@Nullable
private PsiVariable checkCodeFragment(PsiElement refElement) {
PsiElement codeFragement;
if (refElement instanceof PsiParameter
&& ((PsiParameter)refElement).getDeclarationScope() instanceof PsiMethod){
codeFragement = ((PsiMethod)((PsiParameter)refElement).getDeclarationScope()).getBody();
}
else{
codeFragement = ControlFlowUtil.findCodeFragment(refElement);
PsiElement codeFragement = ControlFlowUtil.findCodeFragment(refElement);
if (refElement instanceof PsiParameter) {
final PsiElement declarationScope = ((PsiParameter)refElement).getDeclarationScope();
if (declarationScope instanceof PsiMethod){
codeFragement = ((PsiMethod)declarationScope).getBody();
} else if (declarationScope instanceof PsiLambdaExpression) {
codeFragement = ((PsiLambdaExpression)declarationScope).getBody();
}
}
if (codeFragement == null) return null;
if (myCodeFragment.getContainingFile() == codeFragement.getContainingFile() && //In order for jsp includes to work
@@ -95,7 +95,11 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
while (innerClass != containingClass && innerClass != null) {
final PsiClass parentPsiClass = PsiTreeUtil.getParentOfType(innerClass, PsiClass.class, true);
if (parentPsiClass == containingClass) {
innerClassesWithUsages.add(innerClass);
if (innerClass instanceof PsiLambdaExpression && PsiTreeUtil.isAncestor(innerClass, local, false)) {
innerClassesWithUsages.add(((PsiLambdaExpression)innerClass).getBody());
} else {
innerClassesWithUsages.add(innerClass);
}
innerClassUsages.add(element);
}
innerClass = parentPsiClass;
@@ -113,13 +113,43 @@ public class LambdaUtil {
@Nullable
public static String checkInterfaceFunctional(PsiType functionalInterfaceType) {
final PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(functionalInterfaceType);
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
final PsiClass aClass = resolveResult.getElement();
if (aClass != null) {
if (checkReturnTypeApplicable(resolveResult, aClass)) {
return "No instance of type " + functionalInterfaceType.getPresentableText() + " exists so that lambda expression can be type-checked";
}
return checkInterfaceFunctional(aClass);
}
return null;
}
private static boolean checkReturnTypeApplicable(PsiClassType.ClassResolveResult resolveResult, final PsiClass aClass) {
final MethodSignature methodSignature = getFunction(aClass);
if (methodSignature == null) return false;
for (PsiTypeParameter parameter : aClass.getTypeParameters()) {
if (parameter.getExtendsListTypes().length == 0) continue;
boolean depends = false;
final PsiType substitution = resolveResult.getSubstitutor().substitute(parameter);
if (substitution instanceof PsiWildcardType && !((PsiWildcardType)substitution).isBounded()) {
for (PsiType paramType : methodSignature.getParameterTypes()) {
if (depends(paramType, parameter, new TypeParamsChecker((PsiMethod)null, aClass){
@Override
public boolean startedInference() {
return true;
}
})) {
depends = true;
break;
}
}
if (!depends) return true;
}
}
return false;
}
@Nullable
public static String checkInterfaceFunctional(@NotNull PsiClass psiClass) {
if (psiClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference
@@ -62,6 +62,8 @@ generics.type.argument.cannot.be.of.primitive.type=Type argument cannot be of pr
generics.unchecked.assignment=Unchecked assignment: ''{0}'' to ''{1}''
generics.unchecked.cast=Unchecked cast: ''{0}'' to ''{1}''
generics.unchecked.call.to.member.of.raw.type=Unchecked call to ''{0}'' as a member of raw type ''{1}''
generics.diamond.not.applicable=Diamond operator is not applicable for non-parameterized types
generics.reference.parameters.not.allowed=Reference parameters are not allowed here
foreach.not.applicable=foreach not applicable to type ''{0}''.
illegal.to.access.static.member.from.enum.constructor.or.instance.initializer=It is illegal to access static member ''{0}'' from enum constructor or instance initializer
enum.types.cannot.be.instantiated=Enum types cannot be instantiated
@@ -74,7 +76,7 @@ generics.cannot.catch.type.parameters=Cannot catch type parameters
generics.cannot.instanceof.type.parameters=Class or array expected
illegal.generic.type.for.instanceof=Illegal generic type for instanceof
cannot.select.dot.class.from.type.variable=Cannot select from a type variable
method.doesnot.override.super=Method does not override method from its superclass
method.does.not.override.super=Method does not override method from its superclass
call.to.super.is.not.allowed.in.enum.constructor=Call to super is not allowed in enum constructor
vararg.not.last.parameter=Vararg parameter must be the last in the list
modifiers.for.enum.constants=No modifiers allowed for enum constants
@@ -0,0 +1,10 @@
import java.util.*;
class C {
static final List EMPTY = new ArrayList(0);
void m() {
List<String> list = C.<error descr="Reference parameters are not allowed here"><String></error>EMPTY;
System.out.println(list);
}
}
@@ -40,4 +40,26 @@ class Test1 {
}
}</error>;
}
}
class Test2 {
interface X<T extends Number> {
T foo();
}
{
X<?> x = <error descr="No instance of type X<?> exists so that lambda expression can be type-checked">() -> 123</error>;
X<? extends Number> x1 = () -> 123;
}
}
class Test3 {
interface X<T> {
T foo();
}
{
X<?> x = () -> 123;
}
}
@@ -15,11 +15,9 @@ public class BrokenAlignment {
if (data.inner() != null) {
System.out.println(data.inner().hashCode());
System.out.println(<warning descr="Method invocation 'data.inner().getText().hashCode()' may produce 'java.lang.NullPointerException'">data.inner().getText().hashCode()</warning>);
/*
if (data.inner() != null) {
System.out.println(data.inner().hashCode());
}
*/
data = new Data(null, null);
System.out.println(<warning descr="Method invocation 'data.inner().hashCode()' may produce 'java.lang.NullPointerException'">data.inner().hashCode()</warning>);
@@ -0,0 +1,5 @@
class Test {
public void foo() {
Comparable<String> c = o -> <selection>o.indexOf("foo")</selection>;
}
}
@@ -0,0 +1,9 @@
class Test {
public void foo() {
Comparable<String> c = o -> newMethod(o);
}
private int newMethod(String o) {
return o.indexOf("foo");
}
}
@@ -0,0 +1,24 @@
/*
* Copyright 2000-2012 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.
*/
public class Test2 {
{
Runnable r = () -> {
final String p = "hello";
System.out.println(<caret>p);
};
}
}
@@ -0,0 +1,23 @@
/*
* Copyright 2000-2012 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.
*/
public class Test2 {
{
Runnable r = () -> {
System.out.println("hello");
};
}
}
@@ -1,3 +1,18 @@
/*
* Copyright 2000-2012 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.daemon;
import com.intellij.codeInspection.LocalInspectionTool;
@@ -62,33 +77,30 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testExceptions() throws Exception { doTest(false); }
public void testExplicitMethodParameters() throws Exception { doTest(false); }
public void testExplicitMethodParameters1() throws Exception { doTest(false); }
public void testInferenceWithBounds() throws Exception {doTest(false);}
public void testInferenceWithSuperBounds() throws Exception {doTest(false);}
public void testInferenceWithUpperBoundPromotion() throws Exception {doTest(false);}
public void testVariance() throws Exception {doTest(false);}
public void testForeachTypes() throws Exception {doTest(false);}
public void testRawOverridingMethods() throws Exception {doTest(false);}
public void testAutoboxing() throws Exception {doTest(false);}
public void testAutoboxingMethods() throws Exception {doTest(false);}
public void testAutoboxingConstructors() throws Exception {doTest(false);}
public void testInferenceWithBounds() throws Exception { doTest(false); }
public void testInferenceWithSuperBounds() throws Exception { doTest(false); }
public void testInferenceWithUpperBoundPromotion() throws Exception { doTest(false); }
public void testVariance() throws Exception { doTest(false); }
public void testForeachTypes() throws Exception { doTest(false); }
public void testRawOverridingMethods() throws Exception { doTest(false); }
public void testAutoboxing() throws Exception { doTest(false); }
public void testAutoboxingMethods() throws Exception { doTest(false); }
public void testAutoboxingConstructors() throws Exception { doTest(false); }
public void testEnumWithAbstractMethods() throws Exception { doTest(false); }
public void testEnum() throws Exception { doTest(false); }
public void testSameErasure() throws Exception { doTest(false); }
public void testMethods() throws Exception { doTest(false); }
public void testFields() throws Exception { doTest(false); }
public void testStaticImports() throws Exception { doTest(true); }
public void testUncheckedCasts() throws Exception { doTest(true); }
public void testUncheckedOverriding() throws Exception { doTest(true); }
public void testWildcardTypes() throws Exception { doTest(true); }
public void testConvertibleTypes() throws Exception { doTest(true); }
public void testIntersectionTypes() throws Exception { doTest(true); }
public void testVarargs() throws Exception { doTest(true); }
public void testTypeArgsOnRaw() throws Exception { doTest(false); }
public void testConditionalExpression() throws Exception { doTest(false); }
public void testUnused() throws Exception { doTest(true); }
public void testIDEADEV7337() throws Exception { doTest(true); }
public void testIDEADEV10459() throws Exception { doTest(true); }
public void testIDEADEV12951() throws Exception { doTest(true); }
@@ -101,7 +113,6 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testIDEADEV25778() throws Exception { doTest(true); }
public void testIDEADEV57343() throws Exception { doTest(false); }
public void testSOE() throws Exception { doTest(true); }
public void testGenericExtendException() throws Exception { doTest(false); }
public void testSameErasureDifferentReturnTypes() throws Exception { doTest17Incompatibility(); }
public void testSameErasureDifferentReturnTypesJdk14() throws Exception { doTest(false); }
@@ -118,27 +129,25 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testInnerClassRef() throws Exception { doTest(false); }
public void testPrivateInnerClassRef() throws Exception { doTest(false); }
public void testWideningCastToTypeParam() throws Exception { doTest(false); }
public void testCapturedWildcardAssignments() throws Exception { doTest(false);}
public void testCapturedWildcardAssignments() throws Exception { doTest(false); }
public void testTypeParameterBoundVisibility() throws Exception { doTest17Incompatibility(); }
public void testTypeParameterBoundVisibilityJdk14() throws Exception { doTest(false);}
public void testUncheckedWarningsLevel6() throws Exception { doTest(true);}
public void testIDEA77991() throws Exception { doTest(false);}
public void testIDEA80386() throws Exception { doTest(false);}
public void testIDEA66311() throws Exception { doTest17Incompatibility();}
public void testIDEA88895() throws Exception { doTest17Incompatibility();}
public void testIDEA66311_16() throws Exception { doTest(false);}
public void testIDEA76283() throws Exception {doTest(false);}
public void testIDEA74899() throws Exception {doTest(false);}
public void testIDEA63291() throws Exception {doTest(false);}
public void testIDEA72912() throws Exception {doTest(false);}
public void testIllegalGenericTypeInInstanceof() throws Exception {doTest(false);}
public void testIDEA57339() throws Exception {doTest(false);}
public void testIDEA57340() throws Exception {doTest(false);}
public void testIDEA89771() throws Exception {doTest(false);}
public void testIDEA89801() throws Exception {doTest(false);}
public void testInconvertibleTypes() throws Exception {doTest(false);}
public void testTypeParameterBoundVisibilityJdk14() throws Exception { doTest(false); }
public void testUncheckedWarningsLevel6() throws Exception { doTest(true); }
public void testIDEA77991() throws Exception { doTest(false); }
public void testIDEA80386() throws Exception { doTest(false); }
public void testIDEA66311() throws Exception { doTest17Incompatibility(); }
public void testIDEA88895() throws Exception { doTest17Incompatibility(); }
public void testIDEA66311_16() throws Exception { doTest(false); }
public void testIDEA76283() throws Exception { doTest(false); }
public void testIDEA74899() throws Exception { doTest(false); }
public void testIDEA63291() throws Exception { doTest(false); }
public void testIDEA72912() throws Exception { doTest(false); }
public void testIllegalGenericTypeInInstanceof() throws Exception { doTest(false); }
public void testIDEA57339() throws Exception { doTest(false); }
public void testIDEA57340() throws Exception { doTest(false); }
public void testIDEA89771() throws Exception { doTest(false); }
public void testIDEA89801() throws Exception { doTest(false); }
public void testInconvertibleTypes() throws Exception { doTest(false); }
public void testJavaUtilCollections_NoVerify() throws Exception {
PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));
@@ -540,6 +540,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
doTest();
}
public void testOneLineLambda() throws Exception {
doTest();
}
private void doTestDisabledParam() throws PrepareFailedException {
final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
settings.ELSE_ON_NEW_LINE = true;
@@ -158,6 +158,10 @@ public class InlineLocalTest extends LightCodeInsightTestCase {
doTest(true);
}
public void testLocalVarInsideLambdaBody1() throws Exception {
doTest(true);
}
private void doTest(final boolean inlineDef, String conflictMessage) throws Exception {
try {
doTest(inlineDef);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -25,14 +25,13 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Manages virtual file systems
* Manages virtual file systems.
*
* @see VirtualFileSystem
* @see LocalFileSystem
* @see JarFileSystem
*/
public abstract class VirtualFileManager implements ModificationTracker{
public static final Topic<BulkFileListener> VFS_CHANGES = new Topic<BulkFileListener>("NewVirtualFileSystem changes", BulkFileListener.class);
public abstract class VirtualFileManager implements ModificationTracker {
public static final Topic<BulkFileListener> VFS_CHANGES =
new Topic<BulkFileListener>("NewVirtualFileSystem changes", BulkFileListener.class);
/**
* Gets the instance of <code>VirtualFileManager</code>.
@@ -40,7 +39,7 @@ public abstract class VirtualFileManager implements ModificationTracker{
* @return <code>VirtualFileManager</code>
*/
@NotNull
public static VirtualFileManager getInstance(){
public static VirtualFileManager getInstance() {
return ApplicationManager.getApplication().getComponent(VirtualFileManager.class);
}
@@ -55,12 +54,12 @@ public abstract class VirtualFileManager implements ModificationTracker{
/**
* Refreshes the cached file system information from the physical file system.
* <p>
* <p/>
* This method should be only called within write-action.
* See {@link com.intellij.openapi.application.Application#runWriteAction}.
*
* @param asynchronous if <code>true</code> then the operation will be performed in a separate thread,
* otherwise will be performed immediately
* otherwise will be performed immediately
*/
public abstract void refresh(boolean asynchronous);
@@ -88,14 +87,14 @@ public abstract class VirtualFileManager implements ModificationTracker{
/**
* Refreshes only the part of the file system needed for searching the file by the given URL and finds file
* by the given URL.<br>
*
* <p/>
* This method is useful when the file was created externally and you need to find <code>{@link VirtualFile}</code>
* corresponding to it.<p>
*
* <p/>
* This method should be only called within write-action.
* See {@link com.intellij.openapi.application.Application#runWriteAction}.
*
* @param url the URL
* @param url the URL
* @return <code>{@link VirtualFile}</code> if the file was found, <code>null</code> otherwise
* @see VirtualFileSystem#findFileByPath
* @see VirtualFileSystem#refreshAndFindFileByPath
@@ -106,7 +105,7 @@ public abstract class VirtualFileManager implements ModificationTracker{
/**
* Adds listener to the file system.
*
* @param listener the listener
* @param listener the listener
* @see VirtualFileListener
*/
public abstract void addVirtualFileListener(@NotNull VirtualFileListener listener);
@@ -116,7 +115,7 @@ public abstract class VirtualFileManager implements ModificationTracker{
/**
* Removes listener form the file system.
*
* @param listener the listener
* @param listener the listener
*/
public abstract void removeVirtualFileListener(@NotNull VirtualFileListener listener);
@@ -125,11 +124,11 @@ public abstract class VirtualFileManager implements ModificationTracker{
* file systems.
*
* @param protocol the protocol
* @param path the path
* @param path the path
* @return URL
*/
@NotNull
public static String constructUrl(@NotNull String protocol, @NotNull String path){
public static String constructUrl(@NotNull String protocol, @NotNull String path) {
return protocol + "://" + path;
}
@@ -141,7 +140,7 @@ public abstract class VirtualFileManager implements ModificationTracker{
* @see VirtualFileSystem#getProtocol
*/
@Nullable
public static String extractProtocol(@NotNull String url){
public static String extractProtocol(@NotNull String url) {
int index = url.indexOf("://");
if (index < 0) return null;
return url.substring(0, index);
@@ -155,13 +154,14 @@ public abstract class VirtualFileManager implements ModificationTracker{
* @return path
*/
@NotNull
public static String extractPath(@NotNull String url){
public static String extractPath(@NotNull String url) {
int index = url.indexOf("://");
if (index < 0) return url;
return url.substring(index + "://".length());
}
public abstract void addVirtualFileManagerListener(@NotNull VirtualFileManagerListener listener);
public abstract void addVirtualFileManagerListener(@NotNull VirtualFileManagerListener listener, @NotNull Disposable parentDisposable);
public abstract void removeVirtualFileManagerListener(@NotNull VirtualFileManagerListener listener);
Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

@@ -108,11 +108,7 @@ public class CopyPasteIndentProcessor implements CopyPastePostProcessor<IndentTr
final int offset = getLineStartSafeOffset(initialDocument, lineNumber);
final int caretColumn = caretOffset - offset;
if (bounds.getStartOffset() != offset) { //selection
startLine += 1;
toIndent = Math.abs(bounds.getStartOffset() - offset);
}
else {
if (bounds.getStartOffset() == offset) {
String toString = initialDocument.getText(TextRange.create(offset, initialDocument.getLineEndOffset(lineNumber)));
toIndent = StringUtil.findFirst(toString, new CharFilter() {
@Override
@@ -124,6 +120,12 @@ public class CopyPasteIndentProcessor implements CopyPastePostProcessor<IndentTr
toIndent = caretColumn;
}
}
else if (isNotApplicable(initialDocument, offset))
return;
else { // selection
startLine += 1;
toIndent = Math.abs(bounds.getStartOffset() - offset);
}
}
// actual difference in indentation level
@@ -141,6 +143,11 @@ public class CopyPasteIndentProcessor implements CopyPastePostProcessor<IndentTr
}
indented.set(Boolean.TRUE);
}
private boolean isNotApplicable(DocumentImpl initialDocument, int offset) {
return caretOffset < initialDocument.getTextLength() && !StringUtil
.isEmptyOrSpaces(initialDocument.getText(TextRange.create(offset, caretOffset)));
}
});
//System.out.println("--- after indent ---\n" + document.getText());
}
@@ -227,31 +227,25 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec
if (runnable != null) {
runnable.run();
}
UIUtil.invokeLaterIfNeeded(new Runnable() {
if (myProject.isDisposed() || editor.isDisposed()) return;
foldingModel.runBatchFoldingOperation(new Runnable() {
@Override
public void run() {
if (myProject.isDisposed() || editor.isDisposed()) return;
foldingModel.runBatchFoldingOperation(new Runnable() {
@Override
public void run() {
DocumentFoldingInfo documentFoldingInfo = getDocumentFoldingInfo(document);
Editor[] editors = EditorFactory.getInstance().getEditors(document, myProject);
for (Editor otherEditor : editors) {
if (otherEditor == editor) continue;
documentFoldingInfo.loadFromEditor(otherEditor);
break;
}
documentFoldingInfo.setToEditor(editor);
DocumentFoldingInfo documentFoldingInfo = getDocumentFoldingInfo(document);
Editor[] editors = EditorFactory.getInstance().getEditors(document, myProject);
for (Editor otherEditor : editors) {
if (otherEditor == editor) continue;
documentFoldingInfo.loadFromEditor(otherEditor);
break;
}
documentFoldingInfo.setToEditor(editor);
documentFoldingInfo.clear();
}
});
documentFoldingInfo.clear();
}
});
}
};
editor.getFoldingModel().runBatchFoldingOperationDoNotCollapseCaret(operation);
UIUtil.invokeLaterIfNeeded(operation);
}
@Override
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.impl.smartPointers;
import com.intellij.lang.Language;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.project.Project;
@@ -32,13 +33,19 @@ import org.jetbrains.annotations.NotNull;
class FileElementInfo implements SmartPointerElementInfo {
protected final VirtualFile myVirtualFile;
protected final Project myProject;
protected final Language myLanguage;
public FileElementInfo(@NotNull PsiFile file) {
this(file.getProject(), file.getVirtualFile());
this(file.getProject(), file.getVirtualFile(), file.getLanguage());
}
protected FileElementInfo(@NotNull Project project, VirtualFile virtualFile) {
this(project, virtualFile, null);
}
protected FileElementInfo(@NotNull Project project, VirtualFile virtualFile, Language lang) {
myVirtualFile = virtualFile;
myProject = project;
myLanguage = lang;
}
@Override
@@ -60,7 +67,7 @@ class FileElementInfo implements SmartPointerElementInfo {
@Override
public PsiElement restoreElement() {
return SelfElementInfo.restoreFileFromVirtual(myVirtualFile, myProject);
return SelfElementInfo.restoreFileFromVirtual(myVirtualFile, myProject, myLanguage);
}
@Override
@@ -130,7 +130,6 @@ public abstract class LocalFileSystem extends NewVirtualFileSystem {
/** @deprecated implementation details (to remove in IDEA 13) */
@SuppressWarnings({"UnusedDeclaration"})
@NotNull
String getFileSystemRootPath();
/** @deprecated implementation details (to remove in IDEA 13) */
@@ -256,6 +256,9 @@ public class FileBasedStorage extends XmlElementStorage {
LOG.info("Document was not loaded for " + myFileSpec + " file is " + (file == null ? "null" : "directory"));
return null;
}
else if (file.getLength() == 0) {
return processReadException(null);
}
else {
return loadDocumentImpl(file);
}
@@ -269,12 +272,15 @@ public class FileBasedStorage extends XmlElementStorage {
}
@Nullable
private Document processReadException(final Exception e) {
myBlockSavingTheContent = isProjectOrModuleFile();
private Document processReadException(@Nullable final Exception e) {
boolean contentTruncated = e == null;
myBlockSavingTheContent = isProjectOrModuleFile() && !contentTruncated;
if (!ApplicationManager.getApplication().isUnitTestMode() && !ApplicationManager.getApplication().isHeadlessEnvironment()) {
LOG.info(e);
final String message = "Cannot load settings from file '" + myFile.getPath() + "': " + e.getLocalizedMessage() + "\n" +
getInvalidContentMessage();
if (e != null) {
LOG.info(e);
}
final String message = "Cannot load settings from file '" + myFile.getPath() + "': " + (e == null ? "content truncated" : e.getLocalizedMessage()) + "\n" +
getInvalidContentMessage(contentTruncated);
Notifications.Bus.notify(
new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, "Load Settings", message, NotificationType.WARNING));
}
@@ -286,8 +292,8 @@ public class FileBasedStorage extends XmlElementStorage {
return myIsProjectSettings || myFileSpec.equals("$MODULE_FILE$");
}
private String getInvalidContentMessage() {
return isProjectOrModuleFile() ? "Please correct the file content" : "File content will be recreated";
private String getInvalidContentMessage(boolean contentTruncated) {
return isProjectOrModuleFile() && !contentTruncated ? "Please correct the file content" : "File content will be recreated";
}
private static Document loadDocumentImpl(final VirtualFile file) throws IOException, JDOMException {
@@ -163,9 +163,6 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
if (document != null) {
loadState(result, document.getRootElement());
}
else {
LOG.info("Document was not loaded for " + myFileSpec);
}
if (!myIsProjectSettings && useProvidersData) {
for (RoamingType roamingType : RoamingType.values()) {
@@ -173,11 +170,9 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
try {
if (myStreamProvider.isEnabled()) {
final Document sharedDocument = StorageUtil.loadDocument(myStreamProvider.loadContent(myFileSpec, roamingType));
if (sharedDocument != null) {
filterComponentsDisabledForRoaming(sharedDocument.getRootElement(), roamingType);
filterOutOfDateComponents(sharedDocument.getRootElement());
loadState(result, sharedDocument.getRootElement());
}
}
@@ -186,11 +181,9 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
LOG.warn(e);
}
}
}
}
return result;
}
@@ -83,7 +83,6 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap
/** @deprecated implementation details (to remove in IDEA 13) */
@Override
@NotNull
public String getFileSystemRootPath() {
return myFSRootPath;
}
@@ -0,0 +1,23 @@
/*
* Copyright 2000-2012 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.platform;
/**
* @author Dennis.Ushakov
*/
public interface HideableProjectGenerator {
boolean isHidden();
}
@@ -79,6 +79,11 @@ public class NewDirectoryProjectDialog extends DialogWrapper {
List<DirectoryProjectGenerator> primaryGenerators = ContainerUtil.newArrayList();
List<DirectoryProjectGenerator> otherGenerators = ContainerUtil.newArrayList();
for (DirectoryProjectGenerator generator : generators) {
if (generator instanceof HideableProjectGenerator) {
if (((HideableProjectGenerator)generator).isHidden()) {
continue;
}
}
boolean primary = true;
if (generator instanceof WebProjectGenerator) {
primary = ((WebProjectGenerator) generator).isPrimaryGenerator();
@@ -59,7 +59,7 @@ dataflow.message.npe.field.access=Dereference of <code>#ref</code> #loc may prod
dataflow.message.cce=Casting <code>{0}</code> to <code>#ref</code> #loc may produce <code>java.lang.ClassCastException</code>
dataflow.message.redundant.instanceof=Condition <code>#ref</code> #loc is redundant and can be replaced with <code>!= null</code>
dataflow.message.constant.condition=Condition <code>#ref</code> #loc is always <code>{0}</code>
dataflow.message.constant.condition.whenriched=Condition <code>#ref</code> #loc is always <code>{0}</code> when reached
dataflow.message.constant.condition.when.reached=Condition <code>#ref</code> #loc is always <code>{0}</code> when reached
dataflow.message.unreachable.switch.label=Switch label<code>#ref</code> #loc is unreachable
dataflow.message.pointless.assignment.expression=Condition <code>#ref</code> #loc at the left side of assignment expression is always <code>{0}</code>. Can be simplified to normal assignment
dataflow.message.passing.null.argument=Passing <code>null</code> argument to parameter annotated as @NotNull
@@ -244,7 +244,7 @@
<virtualFileSystem key="https" implementationClass="com.intellij.openapi.vfs.impl.http.HttpsFileSystem"/>
<toolWindow id="Event Log" anchor="bottom" secondary="true"
icon="AllIcons.Ide.Notifications"
icon="AllIcons.Ide.NoNotifications13"
factoryClass="com.intellij.notification.EventLogToolWindowFactory"/>
<projectService serviceInterface="com.intellij.openapi.wm.impl.ProjectFrameBounds"
@@ -557,6 +557,7 @@ public class AllIcons {
public static final Icon Recording_stop = IconLoader.getIcon("/ide/macro/recording_stop.png"); // 16x16
}
public static final Icon NoNotifications13 = IconLoader.getIcon("/ide/noNotifications13.png"); // 13x13
public static final Icon Notifications = IconLoader.getIcon("/ide/notifications.png"); // 16x16
public static final Icon Pipette = IconLoader.getIcon("/ide/pipette.png"); // 18x18
public static final Icon Pipette_rollover = IconLoader.getIcon("/ide/pipette_rollover.png"); // 18x18
@@ -469,6 +469,10 @@
key="non.final.field.in.enum.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.classlayout.NonFinalFieldInEnumInspection"/>
<localInspection language="JAVA" shortName="NonFinalUtilityClass" bundle="com.siyeh.InspectionGadgetsBundle"
key="non.final.utility.class.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.classlayout.NonFinalUtilityClassInspection"/>
<localInspection language="JAVA" shortName="NoopMethodInAbstractClass" bundle="com.siyeh.InspectionGadgetsBundle"
key="noop.method.in.abstract.class.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING"
@@ -1932,6 +1932,7 @@ simplifiable.equals.expression.display.name=Unnecessary 'null' check before 'equ
simplifiable.equals.expression.problem.descriptor=Unnecessary ''null'' check before ''{0}()'' call #loc
simplifiable.equals.expression.quickfix=Flip ''.{0}()'' and remove unnecessary ''null'' check
cast.to.concrete.class.option=Ignore casts to an abstract class type
cast.to.concrete.class.ignore.equals.option=Ignore in equals()
instanceof.interfaces.option=Ignore instanceof abstract class
instance.variable.of.concrete.class.option=Ignore instance fields whose type is an abstract class
local.variable.of.concrete.class.option=Ignore local variables whose type is an abstract class
@@ -1994,3 +1995,6 @@ none=none
private=private
package.local.private=package local & private
protected.package.local.private=protected, package local & private
non.final.utility.class.display.name=Utility class is not final
non.final.utility.class.problem.descriptor=Utility class <code>#ref</code> is not final
0.will.no.longer.be.overridable.by.1={0} will no longer be overridable by {1}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,43 +15,45 @@
*/
package com.siyeh.ig.abstraction;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.MethodUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.JComponent;
import javax.swing.*;
public class CastToConcreteClassInspection extends BaseInspection {
@SuppressWarnings("PublicField")
public boolean ignoreAbstractClasses = false;
@SuppressWarnings("PublicField")
public boolean ignoreInEquals = true;
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"cast.to.concrete.class.display.name");
return InspectionGadgetsBundle.message("cast.to.concrete.class.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
final PsiElement typeElement = (PsiElement)infos[0];
return InspectionGadgetsBundle.message(
"cast.to.concrete.class.problem.descriptor",
typeElement.getText());
final PsiType type= (PsiType)infos[0];
return InspectionGadgetsBundle.message("cast.to.concrete.class.problem.descriptor", type.getPresentableText());
}
@Override
public JComponent createOptionsPanel() {
return new SingleCheckboxOptionsPanel(
InspectionGadgetsBundle.message(
"cast.to.concrete.class.option"),
this, "ignoreAbstractClasses");
final MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
panel.addCheckbox(InspectionGadgetsBundle.message("cast.to.concrete.class.option"), "ignoreAbstractClasses");
panel.addCheckbox(InspectionGadgetsBundle.message("cast.to.concrete.class.ignore.equals.option"), "ignoreInEquals");
return panel;
}
@Override
@@ -59,49 +61,68 @@ public class CastToConcreteClassInspection extends BaseInspection {
return new CastToConcreteClassVisitor();
}
private class CastToConcreteClassVisitor
extends BaseInspectionVisitor {
private class CastToConcreteClassVisitor extends BaseInspectionVisitor {
@Override
public void visitTypeCastExpression(
@NotNull PsiTypeCastExpression expression) {
public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) {
super.visitTypeCastExpression(expression);
final PsiTypeElement typeElement = expression.getCastType();
if (typeElement == null) {
return;
}
if (!ConcreteClassUtil.typeIsConcreteClass(typeElement,
ignoreAbstractClasses)) {
if (!ConcreteClassUtil.typeIsConcreteClass(typeElement, ignoreAbstractClasses)) {
return;
}
registerError(typeElement, typeElement);
if (ignoreInEquals) {
final PsiMethod method = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiClass.class);
if (MethodUtils.isEquals(method)) {
return;
}
}
registerError(typeElement, typeElement.getType());
}
@Override
public void visitMethodCallExpression(
PsiMethodCallExpression expression) {
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
final PsiReferenceExpression methodExpression =
expression.getMethodExpression();
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
@NonNls
final String referenceName = methodExpression.getReferenceName();
if (!"cast".equals(referenceName)) {
return;
}
final PsiExpression qualifier =
methodExpression.getQualifierExpression();
if (!(qualifier instanceof PsiClassObjectAccessExpression)) {
final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (qualifier == null) {
return;
}
final PsiClassObjectAccessExpression classObjectAccessExpression =
(PsiClassObjectAccessExpression)qualifier;
final PsiTypeElement operand =
classObjectAccessExpression.getOperand();
if (!ConcreteClassUtil.typeIsConcreteClass(operand,
ignoreAbstractClasses)) {
final PsiType type = qualifier.getType();
if (!(type instanceof PsiClassType)) {
return;
}
registerMethodCallError(expression, operand);
final PsiClassType classType = (PsiClassType)type;
final PsiClass aClass = classType.resolve();
if (aClass == null) {
return;
}
final String className = aClass.getQualifiedName();
if (!CommonClassNames.JAVA_LANG_CLASS.equals(className)) {
return;
}
final PsiType[] parameters = classType.getParameters();
if (parameters.length != 1) {
return;
}
final PsiType parameter = parameters[0];
if (!ConcreteClassUtil.typeIsConcreteClass(parameter, ignoreAbstractClasses)) {
return;
}
if (ignoreInEquals) {
final PsiMethod method = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiClass.class);
if (MethodUtils.isEquals(method)) {
return;
}
}
registerMethodCallError(expression, parameter);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,30 +21,33 @@ import org.jetbrains.annotations.Nullable;
class ConcreteClassUtil {
private ConcreteClassUtil() {
}
private ConcreteClassUtil() {}
public static boolean typeIsConcreteClass(
@Nullable PsiTypeElement typeElement,
boolean ignoreCastToAbstractClass) {
public static boolean typeIsConcreteClass(@Nullable PsiTypeElement typeElement, boolean ignoreCastToAbstractClass) {
if (typeElement == null) {
return false;
}
final PsiType type = typeElement.getType();
return typeIsConcreteClass(type, ignoreCastToAbstractClass);
}
public static boolean typeIsConcreteClass(@Nullable PsiType type, boolean ignoreCastToAbstractClass) {
if (type == null) {
return false;
}
final PsiType baseType = type.getDeepComponentType();
if (!(baseType instanceof PsiClassType)) {
return false;
}
final PsiClass aClass = ((PsiClassType)baseType).resolve();
final PsiClassType classType = (PsiClassType)baseType;
final PsiClass aClass = classType.resolve();
if (aClass == null) {
return false;
}
if (ignoreCastToAbstractClass &&
aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
if (ignoreCastToAbstractClass && aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
return false;
}
if (aClass.isInterface() || aClass.isEnum() ||
aClass.isAnnotationType()) {
if (aClass.isInterface() || aClass.isEnum() || aClass.isAnnotationType()) {
return false;
}
if (aClass instanceof PsiTypeParameter) {
@@ -0,0 +1,73 @@
/*
* Copyright 2000-2012 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.siyeh.ig.classlayout;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiModifier;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.MakeClassFinalFix;
import com.siyeh.ig.psiutils.UtilityClassUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Bas Leijdekkers
*/
public class NonFinalUtilityClassInspection extends BaseInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return InspectionGadgetsBundle.message("non.final.utility.class.display.name");
}
@NotNull
@Override
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message("non.final.utility.class.problem.descriptor");
}
@Nullable
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
return new MakeClassFinalFix((PsiClass)infos[0]);
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new NonFinalUtilityClassVisitor();
}
private static class NonFinalUtilityClassVisitor extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
// no call to super, so that it doesn't drill down to inner classes
if (!UtilityClassUtil.isUtilityClass(aClass)) {
return;
}
if (aClass.hasModifierProperty(PsiModifier.FINAL)) {
return;
}
registerClassError(aClass, aClass);
}
}
}
@@ -0,0 +1,108 @@
/*
* Copyright 2000-2012 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.siyeh.ig.fixes;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiModifierList;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.ui.ConflictsDialog;
import com.intellij.refactoring.util.RefactoringUIUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import com.intellij.util.Query;
import com.intellij.util.containers.MultiMap;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
import org.jetbrains.annotations.NotNull;
/**
* @author Bas Leijdekkers
*/
public class MakeClassFinalFix extends InspectionGadgetsFix {
private final String className;
public MakeClassFinalFix(PsiClass aClass) {
className = aClass.getName();
}
@Override
@NotNull
public String getName() {
return InspectionGadgetsBundle.message(
"make.class.final.fix.name", className);
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
final PsiElement element = descriptor.getPsiElement();
final PsiClass containingClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
if (containingClass == null) {
return;
}
final PsiModifierList modifierList = containingClass.getModifierList();
if (modifierList == null) {
return;
}
if (!isOnTheFly()) {
if (ClassInheritorsSearch.search(containingClass).findFirst() != null) {
return;
}
modifierList.setModifierProperty(PsiModifier.FINAL, true);
return;
}
final MultiMap<PsiElement, String> conflicts = new MultiMap();
final Query<PsiClass> search = ClassInheritorsSearch.search(containingClass);
search.forEach(new Processor<PsiClass>() {
@Override
public boolean process(PsiClass aClass) {
conflicts.putValue(containingClass, InspectionGadgetsBundle
.message("0.will.no.longer.be.overridable.by.1", RefactoringUIUtil.getDescription(containingClass, false),
RefactoringUIUtil.getDescription(aClass, false)));
return true;
}
});
final boolean conflictsDialogOK;
if (!conflicts.isEmpty()) {
final ConflictsDialog conflictsDialog = new ConflictsDialog(element.getProject(), conflicts, new Runnable() {
@Override
public void run() {
final AccessToken token = WriteAction.start();
try {
modifierList.setModifierProperty(PsiModifier.FINAL, true);
}
finally {
token.finish();
}
}
});
conflictsDialog.show();
conflictsDialogOK = conflictsDialog.isOK();
} else {
conflictsDialogOK = true;
}
if (conflictsDialogOK) {
modifierList.setModifierProperty(PsiModifier.FINAL, true);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2008 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,82 +25,44 @@ import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.MakeClassFinalFix;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.CloneUtils;
import com.siyeh.ig.psiutils.MethodUtils;
import org.jetbrains.annotations.NotNull;
public class OverridableMethodCallDuringObjectConstructionInspection
extends BaseInspection {
public class OverridableMethodCallDuringObjectConstructionInspection extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"overridable.method.call.in.constructor.display.name");
return InspectionGadgetsBundle.message("overridable.method.call.in.constructor.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"overridable.method.call.in.constructor.problem.descriptor");
return InspectionGadgetsBundle.message("overridable.method.call.in.constructor.problem.descriptor");
}
@Override
@NotNull
protected InspectionGadgetsFix[] buildFixes(Object... infos) {
final PsiMethodCallExpression methodCallExpression =
(PsiMethodCallExpression)infos[0];
final PsiClass callClass =
ClassUtils.getContainingClass(methodCallExpression);
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)infos[0];
final PsiClass callClass = ClassUtils.getContainingClass(methodCallExpression);
final PsiMethod method = methodCallExpression.resolveMethod();
if (method == null) {
return InspectionGadgetsFix.EMPTY_ARRAY;
}
final PsiClass containingClass = method.getContainingClass();
if (!containingClass.equals(callClass) ||
MethodUtils.isOverridden(method)) {
if (containingClass == null || !containingClass.equals(callClass) || MethodUtils.isOverridden(method)) {
return InspectionGadgetsFix.EMPTY_ARRAY;
}
final String methodName = method.getName();
if (!ClassUtils.isOverridden(containingClass)) {
return new InspectionGadgetsFix[]{
new MakeClassFinalFix(containingClass),
new MakeMethodFinalFix(methodName)};
}
else {
return new InspectionGadgetsFix[]{
new MakeMethodFinalFix(methodName)};
}
}
private static class MakeClassFinalFix extends InspectionGadgetsFix {
private final String className;
MakeClassFinalFix(PsiClass aClass) {
className = aClass.getName();
}
@NotNull
public String getName() {
return InspectionGadgetsBundle.message(
"make.class.final.fix.name", className);
}
protected void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException {
final PsiElement element = descriptor.getPsiElement();
final PsiClass containingClass =
PsiTreeUtil.getParentOfType(element, PsiClass.class);
if (containingClass == null) {
return;
}
final PsiModifierList modifierList =
containingClass.getModifierList();
if (modifierList == null) {
return;
}
modifierList.setModifierProperty(PsiModifier.FINAL, true);
}
return new InspectionGadgetsFix[]{
new MakeClassFinalFix(containingClass),
new MakeMethodFinalFix(methodName)
};
}
private static class MakeMethodFinalFix extends InspectionGadgetsFix {
@@ -111,42 +73,40 @@ public class OverridableMethodCallDuringObjectConstructionInspection
this.methodName = methodName;
}
@Override
@NotNull
public String getName() {
return InspectionGadgetsBundle.message(
"make.method.final.fix.name", methodName);
}
protected void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException {
@Override
protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
final PsiElement methodName = descriptor.getPsiElement();
final PsiElement methodExpression = methodName.getParent();
final PsiMethodCallExpression methodCall =
(PsiMethodCallExpression)methodExpression.getParent();
final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)methodExpression.getParent();
final PsiMethod method = methodCall.resolveMethod();
assert method != null;
if (method == null) {
return;
}
final PsiModifierList modifierList = method.getModifierList();
modifierList.setModifierProperty(PsiModifier.FINAL, true);
}
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new OverridableMethodCallInConstructorVisitor();
}
private static class OverridableMethodCallInConstructorVisitor
extends BaseInspectionVisitor {
private static class OverridableMethodCallInConstructorVisitor extends BaseInspectionVisitor {
@Override
public void visitMethodCallExpression(
@NotNull PsiMethodCallExpression call) {
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) {
super.visitMethodCallExpression(call);
final PsiMember member =
PsiTreeUtil.getParentOfType(call, PsiMethod.class,
PsiClassInitializer.class);
final PsiMember member = PsiTreeUtil.getParentOfType(call, PsiMethod.class, PsiClassInitializer.class);
if (member instanceof PsiClassInitializer) {
final PsiClassInitializer classInitializer =
(PsiClassInitializer)member;
final PsiClassInitializer classInitializer = (PsiClassInitializer)member;
if (classInitializer.hasModifierProperty(PsiModifier.STATIC)) {
return;
}
@@ -160,13 +120,10 @@ public class OverridableMethodCallDuringObjectConstructionInspection
else {
return;
}
final PsiReferenceExpression methodExpression =
call.getMethodExpression();
final PsiExpression qualifier =
methodExpression.getQualifierExpression();
final PsiReferenceExpression methodExpression = call.getMethodExpression();
final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (qualifier != null) {
if (!(qualifier instanceof PsiThisExpression
|| qualifier instanceof PsiSuperExpression)) {
if (!(qualifier instanceof PsiThisExpression || qualifier instanceof PsiSuperExpression)) {
return;
}
}
@@ -177,15 +134,12 @@ public class OverridableMethodCallDuringObjectConstructionInspection
if (containingClass.hasModifierProperty(PsiModifier.FINAL)) {
return;
}
final PsiMethod calledMethod =
(PsiMethod)methodExpression.resolve();
final PsiMethod calledMethod = (PsiMethod)methodExpression.resolve();
if (calledMethod == null || !PsiUtil.canBeOverriden(calledMethod)) {
return;
}
final PsiClass calledMethodClass =
calledMethod.getContainingClass();
if (calledMethodClass == null ||
!calledMethodClass.equals(containingClass)) {
final PsiClass calledMethodClass = calledMethod.getContainingClass();
if (calledMethodClass == null || !calledMethodClass.equals(containingClass)) {
return;
}
registerMethodCallError(call, call);
@@ -198,12 +152,10 @@ public class OverridableMethodCallDuringObjectConstructionInspection
if (CloneUtils.isClone(method)) {
return true;
}
if (MethodUtils.simpleMethodMatches(method, null, "void",
"readObject", "java.io.ObjectInputStream")) {
if (MethodUtils.simpleMethodMatches(method, null, "void", "readObject", "java.io.ObjectInputStream")) {
return true;
}
return MethodUtils.simpleMethodMatches(method, null, "void",
"readObjectNoData");
return MethodUtils.simpleMethodMatches(method, null, "void", "readObjectNoData");
}
}
}
@@ -16,10 +16,8 @@
package com.siyeh.ig.psiutils;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.Query;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
@@ -223,10 +221,4 @@ public class ClassUtils {
return inSamePackage(baseClass, referencedClass);
}
}
public static boolean isOverridden(PsiClass aClass) {
final Query<PsiClass> query = ClassInheritorsSearch.search(aClass);
final PsiClass result = query.findFirst();
return result != null;
}
}
@@ -5,7 +5,9 @@ Such declarations may represent a failure of abstraction, and may make testing m
Declarations whose classes come from system or third-party libraries will not be reported by this inspection.
<!-- tooltip end -->
<p>
Use the checkbox below to have this inspection ignore casts to abstract classes.
Use the first checkbox below to have this inspection ignore casts to abstract classes.
<p>
Use the second checkbox below to have this inspection ignore casts inside <code>equals()</code> methods.
<p>
<small>Powered by InspectionGadgets</small>
</body>
@@ -0,0 +1,10 @@
<html>
<body>
This inspection reports utility classes which are not final.
Utility classes have all fields and methods declared <b>static</b>. Giving such classes making them <b>final</b>
prevents them from being inadvertently subclassed.
<!-- tooltip end -->
<p>
<small>New in 12, Powered by InspectionGadgets</small>
</body>
</html>
@@ -0,0 +1,23 @@
package com.siyeh.igtest.abstraction.cast_to_concrete_class;
class CastToConcreteClass {
private String field;
@Override
public boolean equals(Object obj) {
try {
CastToConcreteClass c = (CastToConcreteClass)obj;
return c.field.equals(field);
} catch (ClassCastException e) {
return false;
}
}
void foo(Object o) {
CastToConcreteClass c = (CastToConcreteClass)o;
CastToConcreteClass c2 = CastToConcreteClass.class.cast(o);
final Class<CastToConcreteClass> aClass = CastToConcreteClass.class;
final CastToConcreteClass c3 = aClass.cast(o);
}
}
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>CastToConcreteClass.java</file>
<line>18</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cast to a concrete class</problem_class>
<description>Cast to concrete class &lt;code&gt;CastToConcreteClass&lt;/code&gt; #loc</description>
</problem>
<problem>
<file>CastToConcreteClass.java</file>
<line>19</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cast to a concrete class</problem_class>
<description>Cast to concrete class &lt;code&gt;CastToConcreteClass&lt;/code&gt; #loc</description>
</problem>
<problem>
<file>CastToConcreteClass.java</file>
<line>21</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cast to a concrete class</problem_class>
<description>Cast to concrete class &lt;code&gt;CastToConcreteClass&lt;/code&gt; #loc</description>
</problem>
</problems>
@@ -0,0 +1,10 @@
package com.siyeh.igtest.classlayout.non_final_utility_class;
class NonFinalUtilityClass {
public static void foo() {}
}
final class FinalUtilityClass {
public static void foo() {}
}
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>NonFinalUtilityClass.java</file>
<line>4</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Utility class is not final</problem_class>
<description>Utility class &lt;code&gt;NonFinalUtilityClass&lt;/code&gt; is not final</description>
</problem>
</problems>
@@ -0,0 +1,12 @@
package com.siyeh.ig.abstraction;
import com.siyeh.ig.IGInspectionTestCase;
public class CastToConcreteClassInspectionTest extends IGInspectionTestCase {
public void test() throws Exception {
final CastToConcreteClassInspection tool = new CastToConcreteClassInspection();
tool.ignoreInEquals = true;
doTest("com/siyeh/igtest/abstraction/cast_to_concrete_class", tool);
}
}
@@ -0,0 +1,10 @@
package com.siyeh.ig.classlayout;
import com.siyeh.ig.IGInspectionTestCase;
public class NonFinalUtilityClassInspectionTest extends IGInspectionTestCase {
public void test() throws Exception {
doTest("com/siyeh/igtest/classlayout/non_final_utility_class", new NonFinalUtilityClassInspection());
}
}
@@ -173,7 +173,10 @@ public class ReplaceLambdaWithAnonymousIntention extends Intention {
if (disabled[0]) return false;
}
final PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType();
return functionalInterfaceType != null && LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType) != null && LambdaUtil.isLambdaFullyInferred(lambdaExpression, functionalInterfaceType);
return functionalInterfaceType != null &&
LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType) != null &&
LambdaUtil.isLambdaFullyInferred(lambdaExpression, functionalInterfaceType) &&
LambdaUtil.checkInterfaceFunctional(functionalInterfaceType) == null;
}
return false;
}
@@ -17,10 +17,12 @@
package com.intellij.tasks.actions;
import com.intellij.ide.DataManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.*;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.LocalChangeList;
@@ -52,11 +54,11 @@ public class SwitchTaskAction extends BaseTaskAction {
DataContext dataContext = e.getDataContext();
final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
assert project != null;
final ListPopupImpl popup = createPopup(dataContext, true);
final ListPopupImpl popup = createPopup(dataContext, null, true);
popup.showCenteredInCurrentWindow(project);
}
public static ListPopupImpl createPopup(final DataContext dataContext, boolean withTitle) {
public static ListPopupImpl createPopup(final DataContext dataContext, @Nullable final Runnable onDispose, boolean withTitle) {
final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
final Ref<Boolean> shiftPressed = Ref.create(false);
final Ref<JComponent> componentRef = Ref.create();
@@ -98,6 +100,14 @@ public class SwitchTaskAction extends BaseTaskAction {
};
final ListPopupImpl popup = (ListPopupImpl)JBPopupFactory.getInstance().createListPopup(step);
if (onDispose != null) {
Disposer.register(popup, new Disposable() {
@Override
public void dispose() {
onDispose.run();
}
});
}
componentRef.set(popup.getComponent());
if (items.size() <= 2) {
return popup;
@@ -66,7 +66,7 @@ public class SwitchTaskCombo extends ComboBoxAction implements DumbAware {
@Override
protected JBPopup createPopup(Runnable onDispose) {
return SwitchTaskAction.createPopup(DataManager.getInstance().getDataContext(this), false);
return SwitchTaskAction.createPopup(DataManager.getInstance().getDataContext(this), onDispose, false);
}
};
}