com.liferay.source.formatter.checkstyle.check.UnusedMethodCheck Maven / Gradle / Ivy
The newest version!
/**
* SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
*/
package com.liferay.source.formatter.checkstyle.check;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.FullIdent;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import com.puppycrawl.tools.checkstyle.utils.AnnotationUtil;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* @author Hugo Huijser
*/
public class UnusedMethodCheck extends BaseCheck {
@Override
public int[] getDefaultTokens() {
return new int[] {TokenTypes.CLASS_DEF};
}
@Override
protected void doVisitToken(DetailAST detailAST) {
DetailAST parentDetailAST = detailAST.getParent();
if (parentDetailAST != null) {
return;
}
List methodDefinitionDetailASTList = getAllChildTokens(
detailAST, true, TokenTypes.METHOD_DEF);
if (methodDefinitionDetailASTList.isEmpty()) {
return;
}
List allowedMethodNames = getAttributeValues(
_ALLOWED_METHOD_NAMES_KEY);
Map> referencedMethodNamesMap =
_getReferencedMethodNamesMap(detailAST);
outerLoop:
for (DetailAST methodDefinitionDetailAST :
methodDefinitionDetailASTList) {
DetailAST modifiersDetailAST =
methodDefinitionDetailAST.findFirstToken(TokenTypes.MODIFIERS);
if (!modifiersDetailAST.branchContains(
TokenTypes.LITERAL_PRIVATE) ||
AnnotationUtil.containsAnnotation(methodDefinitionDetailAST) ||
_hasSuppressUnusedWarningsAnnotation(
methodDefinitionDetailAST)) {
continue;
}
String name = getName(methodDefinitionDetailAST);
if (allowedMethodNames.contains(name)) {
continue;
}
DetailAST parametersDetailAST =
methodDefinitionDetailAST.findFirstToken(TokenTypes.PARAMETERS);
Set parameterCountSet = referencedMethodNamesMap.get(name);
if (parameterCountSet == null) {
log(methodDefinitionDetailAST, _MSG_UNUSED_METHOD, name);
continue;
}
if (parameterCountSet.contains(-1)) {
continue;
}
List parameterDefinitionDetailASTList =
getAllChildTokens(
parametersDetailAST, false, TokenTypes.PARAMETER_DEF);
int parameterCount = parameterDefinitionDetailASTList.size();
boolean varArgs = false;
if (parameterCount > 0) {
DetailAST lastParameterDefinitionDetailAST =
parameterDefinitionDetailASTList.get(
parameterDefinitionDetailASTList.size() - 1);
if (lastParameterDefinitionDetailAST.branchContains(
TokenTypes.ELLIPSIS)) {
varArgs = true;
}
}
if (varArgs) {
for (int curParameterCount : parameterCountSet) {
if (curParameterCount >= (parameterCount - 1)) {
continue outerLoop;
}
}
log(methodDefinitionDetailAST, _MSG_UNUSED_METHOD, name);
}
else if (!parameterCountSet.contains(parameterCount)) {
log(methodDefinitionDetailAST, _MSG_UNUSED_METHOD, name);
}
}
}
private Map> _addMapEntry(
Map> map, String key, int value) {
Set set = map.get(key);
if (set == null) {
set = new HashSet<>();
}
set.add(value);
map.put(key, set);
return map;
}
private Map> _getReferencedMethodNamesMap(
DetailAST classDefinitionDetailAST) {
Map> referencedMethodNamesMap = new HashMap<>();
List methodCallDetailASTList = getAllChildTokens(
classDefinitionDetailAST, true, TokenTypes.METHOD_CALL);
for (DetailAST methodCallDetailAST : methodCallDetailASTList) {
DetailAST nameDetailAST = methodCallDetailAST.getFirstChild();
if (nameDetailAST.getType() == TokenTypes.DOT) {
nameDetailAST = nameDetailAST.getLastChild();
}
DetailAST elistDetailAST = methodCallDetailAST.findFirstToken(
TokenTypes.ELIST);
int parameterCount = 0;
int childCount = elistDetailAST.getChildCount();
if (childCount > 0) {
parameterCount = (childCount + 1) / 2;
}
referencedMethodNamesMap = _addMapEntry(
referencedMethodNamesMap, nameDetailAST.getText(),
parameterCount);
}
List methodReferenceDetailASTList = getAllChildTokens(
classDefinitionDetailAST, true, TokenTypes.METHOD_REF);
for (DetailAST methodReferenceDetailAST :
methodReferenceDetailASTList) {
DetailAST lastChildDetailAST =
methodReferenceDetailAST.getLastChild();
referencedMethodNamesMap = _addMapEntry(
referencedMethodNamesMap, lastChildDetailAST.getText(), -1);
}
List literalNewDetailASTList = getAllChildTokens(
classDefinitionDetailAST, true, TokenTypes.LITERAL_NEW);
for (DetailAST literalNewDetailAST : literalNewDetailASTList) {
DetailAST firstChildDetailAST = literalNewDetailAST.getFirstChild();
if ((firstChildDetailAST == null) ||
(firstChildDetailAST.getType() != TokenTypes.IDENT) ||
!Objects.equals(firstChildDetailAST.getText(), "MethodKey")) {
continue;
}
DetailAST elistDetailAST = literalNewDetailAST.findFirstToken(
TokenTypes.ELIST);
List exprDetailASTList = getAllChildTokens(
elistDetailAST, false, TokenTypes.EXPR);
if (exprDetailASTList.size() < 2) {
continue;
}
DetailAST exprDetailAST = exprDetailASTList.get(1);
firstChildDetailAST = exprDetailAST.getFirstChild();
if (firstChildDetailAST.getType() == TokenTypes.STRING_LITERAL) {
String text = firstChildDetailAST.getText();
referencedMethodNamesMap = _addMapEntry(
referencedMethodNamesMap,
text.substring(1, text.length() - 1),
exprDetailASTList.size() - 2);
}
}
List annotationDetailASTList = getAllChildTokens(
classDefinitionDetailAST, true, TokenTypes.ANNOTATION);
for (DetailAST annotationDetailAST : annotationDetailASTList) {
DetailAST atDetailAST = annotationDetailAST.findFirstToken(
TokenTypes.AT);
FullIdent fullIdent = FullIdent.createFullIdent(
atDetailAST.getNextSibling());
String annotationName = fullIdent.getText();
if (!annotationName.endsWith("Reference")) {
continue;
}
List annotationMemberValuePairDetailASTList =
getAllChildTokens(
annotationDetailAST, false,
TokenTypes.ANNOTATION_MEMBER_VALUE_PAIR);
for (DetailAST annotationMemberValuePairDetailAST :
annotationMemberValuePairDetailASTList) {
DetailAST firstChildDetailAST =
annotationMemberValuePairDetailAST.getFirstChild();
String propertyName = firstChildDetailAST.getText();
if (!propertyName.equals("unbind")) {
continue;
}
DetailAST nextSiblingDetailAST =
firstChildDetailAST.getNextSibling();
fullIdent = FullIdent.createFullIdentBelow(
nextSiblingDetailAST.getNextSibling());
String propertyValueName = fullIdent.getText();
if (propertyValueName.matches("\".*\"")) {
referencedMethodNamesMap = _addMapEntry(
referencedMethodNamesMap,
propertyValueName.substring(
1, propertyValueName.length() - 1),
1);
}
}
}
return referencedMethodNamesMap;
}
private boolean _hasSuppressUnusedWarningsAnnotation(
DetailAST methodDefinitionDetailAST) {
DetailAST annotationDetailAST = AnnotationUtil.getAnnotation(
methodDefinitionDetailAST, "SuppressWarnings");
if (annotationDetailAST == null) {
return false;
}
List literalStringDetailASTList = getAllChildTokens(
annotationDetailAST, true, TokenTypes.STRING_LITERAL);
for (DetailAST literalStringDetailAST : literalStringDetailASTList) {
String s = literalStringDetailAST.getText();
if (s.equals("\"unused\"")) {
return true;
}
}
return false;
}
private static final String _ALLOWED_METHOD_NAMES_KEY =
"allowedMethodNames";
private static final String _MSG_UNUSED_METHOD = "method.unused";
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy