|
|
|
@@ -46,12 +46,16 @@ import static com.intellij.util.ObjectUtils.tryCast;
|
|
|
|
|
public class Java9CollectionFactoryInspection extends BaseLocalInspectionTool {
|
|
|
|
|
private static final CallMatcher UNMODIFIABLE_SET =
|
|
|
|
|
CallMatcher.staticCall(CommonClassNames.JAVA_UTIL_COLLECTIONS, "unmodifiableSet").parameterCount(1);
|
|
|
|
|
private static final CallMatcher UNMODIFIABLE_MAP =
|
|
|
|
|
CallMatcher.staticCall(CommonClassNames.JAVA_UTIL_COLLECTIONS, "unmodifiableMap").parameterCount(1);
|
|
|
|
|
private static final CallMatcher UNMODIFIABLE_LIST =
|
|
|
|
|
CallMatcher.staticCall(CommonClassNames.JAVA_UTIL_COLLECTIONS, "unmodifiableList").parameterCount(1);
|
|
|
|
|
private static final CallMatcher ARRAYS_AS_LIST =
|
|
|
|
|
CallMatcher.staticCall(CommonClassNames.JAVA_UTIL_ARRAYS, "asList");
|
|
|
|
|
private static final CallMatcher COLLECTION_ADD =
|
|
|
|
|
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "add").parameterCount(1);
|
|
|
|
|
private static final CallMatcher MAP_PUT =
|
|
|
|
|
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_MAP, "put").parameterCount(2);
|
|
|
|
|
private static final CallMatcher STREAM_COLLECT =
|
|
|
|
|
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_STREAM_STREAM, "collect").parameterCount(1);
|
|
|
|
|
private static final CallMatcher STREAM_OF =
|
|
|
|
@@ -63,6 +67,7 @@ public class Java9CollectionFactoryInspection extends BaseLocalInspectionTool {
|
|
|
|
|
|
|
|
|
|
private static final CallMapper<PrepopulatedCollectionModel> MAPPER = new CallMapper<PrepopulatedCollectionModel>()
|
|
|
|
|
.register(UNMODIFIABLE_SET, call -> PrepopulatedCollectionModel.fromSet(call.getArgumentList().getExpressions()[0]))
|
|
|
|
|
.register(UNMODIFIABLE_MAP, call -> PrepopulatedCollectionModel.fromMap(call.getArgumentList().getExpressions()[0]))
|
|
|
|
|
.register(UNMODIFIABLE_LIST, call -> PrepopulatedCollectionModel.fromList(call.getArgumentList().getExpressions()[0]));
|
|
|
|
|
|
|
|
|
|
public boolean IGNORE_NON_CONSTANT = false;
|
|
|
|
@@ -122,7 +127,8 @@ public class Java9CollectionFactoryInspection extends BaseLocalInspectionTool {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean isValid() {
|
|
|
|
|
return !myHasNulls && !myRepeatingKeys;
|
|
|
|
|
boolean mapOfTooManyParameters = myType.equals("Map") && myContent.size() > 20;
|
|
|
|
|
return !myHasNulls && !myRepeatingKeys && !mapOfTooManyParameters;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private StreamEx<PsiExpression> keyExpressions() {
|
|
|
|
@@ -143,54 +149,56 @@ public class Java9CollectionFactoryInspection extends BaseLocalInspectionTool {
|
|
|
|
|
if (ARRAYS_AS_LIST.test(call)) {
|
|
|
|
|
return new PrepopulatedCollectionModel(Arrays.asList(call.getArgumentList().getExpressions()), Collections.emptyList(), "List");
|
|
|
|
|
}
|
|
|
|
|
if(STREAM_COLLECT.test(call) && COLLECTORS_TO_LIST.matches(call.getArgumentList().getExpressions()[0])) {
|
|
|
|
|
PsiMethodCallExpression qualifier = MethodCallUtils.getQualifierMethodCall(call);
|
|
|
|
|
if(STREAM_OF.matches(qualifier)) {
|
|
|
|
|
return new PrepopulatedCollectionModel(Arrays.asList(qualifier.getArgumentList().getExpressions()), Collections.emptyList(),
|
|
|
|
|
"List");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return fromCollect(call, "List", COLLECTORS_TO_LIST);
|
|
|
|
|
}
|
|
|
|
|
if(listDefinition instanceof PsiNewExpression) {
|
|
|
|
|
return fromNewExpression((PsiNewExpression)listDefinition, "List", CommonClassNames.JAVA_UTIL_ARRAY_LIST);
|
|
|
|
|
}
|
|
|
|
|
if (listDefinition instanceof PsiReferenceExpression) {
|
|
|
|
|
PsiLocalVariable variable = tryCast(((PsiReferenceExpression)listDefinition).resolve(), PsiLocalVariable.class);
|
|
|
|
|
if (variable != null) {
|
|
|
|
|
return fromVariable(variable, listDefinition, "List", CommonClassNames.JAVA_UTIL_ARRAY_LIST);
|
|
|
|
|
}
|
|
|
|
|
return fromVariable((PsiReferenceExpression)listDefinition, "List", CommonClassNames.JAVA_UTIL_ARRAY_LIST, COLLECTION_ADD);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static PrepopulatedCollectionModel fromSet(PsiExpression setDefinition) {
|
|
|
|
|
setDefinition = PsiUtil.skipParenthesizedExprDown(setDefinition);
|
|
|
|
|
if(setDefinition instanceof PsiNewExpression) {
|
|
|
|
|
if (setDefinition instanceof PsiMethodCallExpression) {
|
|
|
|
|
return fromCollect((PsiMethodCallExpression)setDefinition, "Set", COLLECTORS_TO_SET);
|
|
|
|
|
}
|
|
|
|
|
if (setDefinition instanceof PsiNewExpression) {
|
|
|
|
|
return fromNewExpression((PsiNewExpression)setDefinition, "Set", CommonClassNames.JAVA_UTIL_HASH_SET);
|
|
|
|
|
}
|
|
|
|
|
if(setDefinition instanceof PsiMethodCallExpression) {
|
|
|
|
|
PsiMethodCallExpression call = (PsiMethodCallExpression)setDefinition;
|
|
|
|
|
if(STREAM_COLLECT.test(call) && COLLECTORS_TO_SET.matches(call.getArgumentList().getExpressions()[0])) {
|
|
|
|
|
PsiMethodCallExpression qualifier = MethodCallUtils.getQualifierMethodCall(call);
|
|
|
|
|
if(STREAM_OF.matches(qualifier)) {
|
|
|
|
|
return new PrepopulatedCollectionModel(Arrays.asList(qualifier.getArgumentList().getExpressions()), Collections.emptyList(),
|
|
|
|
|
"Set");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (setDefinition instanceof PsiReferenceExpression) {
|
|
|
|
|
PsiLocalVariable variable = tryCast(((PsiReferenceExpression)setDefinition).resolve(), PsiLocalVariable.class);
|
|
|
|
|
if (variable != null) {
|
|
|
|
|
return fromVariable(variable, setDefinition, "Set", CommonClassNames.JAVA_UTIL_HASH_SET);
|
|
|
|
|
return fromVariable((PsiReferenceExpression)setDefinition, "Set", CommonClassNames.JAVA_UTIL_HASH_SET, COLLECTION_ADD);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static PrepopulatedCollectionModel fromMap(PsiExpression mapDefinition) {
|
|
|
|
|
mapDefinition = PsiUtil.skipParenthesizedExprDown(mapDefinition);
|
|
|
|
|
if (mapDefinition instanceof PsiReferenceExpression) {
|
|
|
|
|
return fromVariable((PsiReferenceExpression)mapDefinition, "Map", CommonClassNames.JAVA_UTIL_HASH_MAP, MAP_PUT);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Nullable
|
|
|
|
|
private static PrepopulatedCollectionModel fromCollect(PsiMethodCallExpression call, String typeName, CallMatcher collector) {
|
|
|
|
|
if (STREAM_COLLECT.test(call) && collector.matches(call.getArgumentList().getExpressions()[0])) {
|
|
|
|
|
PsiMethodCallExpression qualifier = MethodCallUtils.getQualifierMethodCall(call);
|
|
|
|
|
if (STREAM_OF.matches(qualifier)) {
|
|
|
|
|
return new PrepopulatedCollectionModel(Arrays.asList(qualifier.getArgumentList().getExpressions()), Collections.emptyList(),
|
|
|
|
|
typeName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Nullable
|
|
|
|
|
private static PrepopulatedCollectionModel fromVariable(PsiLocalVariable variable,
|
|
|
|
|
PsiExpression expression,
|
|
|
|
|
String typeName, String collectionClass) {
|
|
|
|
|
private static PrepopulatedCollectionModel fromVariable(PsiReferenceExpression expression,
|
|
|
|
|
String typeName, String collectionClass, CallMatcher addMethod) {
|
|
|
|
|
PsiLocalVariable variable = tryCast(expression.resolve(), PsiLocalVariable.class);
|
|
|
|
|
if (variable == null) return null;
|
|
|
|
|
PsiCodeBlock block = PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
|
|
|
|
|
PsiDeclarationStatement declaration = PsiTreeUtil.getParentOfType(variable, PsiDeclarationStatement.class);
|
|
|
|
|
if (block == null || declaration == null) return null;
|
|
|
|
@@ -211,9 +219,9 @@ public class Java9CollectionFactoryInspection extends BaseLocalInspectionTool {
|
|
|
|
|
if (PsiTreeUtil.isAncestor(cur, expression, false)) break;
|
|
|
|
|
if (!(cur instanceof PsiExpressionStatement)) return null;
|
|
|
|
|
PsiMethodCallExpression call = tryCast(((PsiExpressionStatement)cur).getExpression(), PsiMethodCallExpression.class);
|
|
|
|
|
if (!COLLECTION_ADD.test(call)) return null;
|
|
|
|
|
if (!addMethod.test(call)) return null;
|
|
|
|
|
if (!refs.remove(call.getMethodExpression().getQualifierExpression())) return null;
|
|
|
|
|
contents.add(call.getArgumentList().getExpressions()[0]);
|
|
|
|
|
contents.addAll(Arrays.asList(call.getArgumentList().getExpressions()));
|
|
|
|
|
elementsToRemove.add(cur);
|
|
|
|
|
}
|
|
|
|
|
if (!refs.isEmpty()) return null;
|
|
|
|
|