All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.source.formatter.checkstyle.check.JSONUtilCheck 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.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;

import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.FullIdent;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author Hugo Huijser
 */
public class JSONUtilCheck extends BaseChainedMethodCheck {

	@Override
	public int[] getDefaultTokens() {
		return new int[] {TokenTypes.ASSIGN, TokenTypes.METHOD_CALL};
	}

	@Override
	protected void doVisitToken(DetailAST detailAST) {
		if (detailAST.getType() == TokenTypes.METHOD_CALL) {
			_checkChainedPutCalls(detailAST);
			_checkStringValueOfCalls(detailAST);
			_checkToJSONStringCalls(detailAST);

			return;
		}

		DetailAST parentDetailAST = detailAST.getParent();

		if ((parentDetailAST.getType() != TokenTypes.EXPR) &&
			(parentDetailAST.getType() != TokenTypes.VARIABLE_DEF)) {

			return;
		}

		DetailAST nextSiblingDetailAST = parentDetailAST.getNextSibling();

		if ((nextSiblingDetailAST == null) ||
			(nextSiblingDetailAST.getType() != TokenTypes.SEMI)) {

			return;
		}

		DetailAST methodCallDetailAST = _getMethodCallDetailAST(
			detailAST, parentDetailAST);

		if (methodCallDetailAST == null) {
			return;
		}

		DetailAST elistDetailAST = methodCallDetailAST.findFirstToken(
			TokenTypes.ELIST);

		if (elistDetailAST.getChildCount() > 0) {
			return;
		}

		DetailAST firstChildDetailAST = methodCallDetailAST.getFirstChild();

		FullIdent fullIdent1 = FullIdent.createFullIdent(firstChildDetailAST);

		String methodName = fullIdent1.getText();

		if (!methodName.equals("JSONFactoryUtil.createJSONArray") &&
			!methodName.equals("JSONFactoryUtil.createJSONObject")) {

			return;
		}

		String variableName = getVariableName(detailAST, parentDetailAST);

		if (variableName == null) {
			return;
		}

		while (true) {
			nextSiblingDetailAST = nextSiblingDetailAST.getNextSibling();

			if (nextSiblingDetailAST == null) {
				return;
			}

			FullIdent fullIdent2 = getMethodCallFullIdent(
				nextSiblingDetailAST, variableName, "put");

			if (fullIdent2 != null) {
				log(
					detailAST, _MSG_USE_JSON_UTIL_PUT, methodName,
					fullIdent1.getLineNo(), variableName + ".put",
					fullIdent2.getLineNo(), "JSONUtil.put");
			}

			if (containsVariableName(
					nextSiblingDetailAST, variableName, true)) {

				return;
			}
		}
	}

	private void _checkChainedPutCalls(DetailAST methodCallDetailAST) {
		DetailAST firstChildDetailAST = methodCallDetailAST.getFirstChild();

		if (firstChildDetailAST.getType() != TokenTypes.DOT) {
			return;
		}

		FullIdent fullIdent = FullIdent.createFullIdent(firstChildDetailAST);

		if (!Objects.equals(fullIdent.getText(), "JSONUtil.put")) {
			return;
		}

		DetailAST elistDetailAST = methodCallDetailAST.findFirstToken(
			TokenTypes.ELIST);

		if (elistDetailAST.getChildCount() != 1) {
			return;
		}

		DetailAST parentDetailAST = methodCallDetailAST.getParent();

		if (parentDetailAST.getType() != TokenTypes.DOT) {
			return;
		}

		parentDetailAST = parentDetailAST.getParent();

		if (parentDetailAST.getType() != TokenTypes.METHOD_CALL) {
			return;
		}

		DetailAST nextSiblingDetailAST = methodCallDetailAST.getNextSibling();

		if ((nextSiblingDetailAST.getType() == TokenTypes.IDENT) &&
			Objects.equals(nextSiblingDetailAST.getText(), "put")) {

			log(methodCallDetailAST, _MSG_USE_JSON_UTIL_PUT_ALL);
		}
	}

	private void _checkStringValueOfCalls(DetailAST detailAST) {
		DetailAST firstChildDetailAST = detailAST.getFirstChild();

		if (firstChildDetailAST.getType() != TokenTypes.DOT) {
			return;
		}

		FullIdent fullIdent = FullIdent.createFullIdent(firstChildDetailAST);

		if (!Objects.equals(fullIdent.getText(), "String.valueOf")) {
			return;
		}

		DetailAST elistDetailAST = detailAST.findFirstToken(TokenTypes.ELIST);

		if (elistDetailAST == null) {
			return;
		}

		firstChildDetailAST = elistDetailAST.getFirstChild();

		if ((firstChildDetailAST == null) ||
			(firstChildDetailAST.getType() != TokenTypes.EXPR)) {

			return;
		}

		firstChildDetailAST = firstChildDetailAST.getFirstChild();

		if ((firstChildDetailAST == null) ||
			(firstChildDetailAST.getType() != TokenTypes.METHOD_CALL)) {

			return;
		}

		List methodCallDetailASTList = getAllChildTokens(
			firstChildDetailAST, true, TokenTypes.METHOD_CALL);

		if (methodCallDetailASTList.isEmpty()) {
			firstChildDetailAST = firstChildDetailAST.getFirstChild();

			if (firstChildDetailAST.getType() != TokenTypes.DOT) {
				return;
			}

			fullIdent = FullIdent.createFullIdent(firstChildDetailAST);

			if (Objects.equals(fullIdent.getText(), "JSONUtil.put") ||
				Objects.equals(fullIdent.getText(), "JSONUtil.putAll")) {

				log(detailAST, _MSG_USE_JSON_UTIL_TO_STRING_1);
			}

			return;
		}

		List chainedMethodNames = new ArrayList<>();

		for (DetailAST methodCallDetailAST : methodCallDetailASTList) {
			DetailAST dotDetailAST = methodCallDetailAST.findFirstToken(
				TokenTypes.DOT);

			if (dotDetailAST != null) {
				List childMethodCallDetailASTList =
					getAllChildTokens(
						dotDetailAST, false, TokenTypes.METHOD_CALL);

				if (!childMethodCallDetailASTList.isEmpty()) {
					continue;
				}
			}

			BaseCheck.ChainInformation chainInformation = getChainInformation(
				methodCallDetailAST);

			chainedMethodNames = chainInformation.getMethodNames();
		}

		for (String chainedMethodName : chainedMethodNames) {
			if (!chainedMethodName.equals("put") &&
				!chainedMethodName.equals("putAll")) {

				return;
			}
		}

		DetailAST methodCallDetailAST = methodCallDetailASTList.get(
			methodCallDetailASTList.size() - 1);

		firstChildDetailAST = methodCallDetailAST.getFirstChild();

		if (firstChildDetailAST.getType() != TokenTypes.DOT) {
			return;
		}

		fullIdent = FullIdent.createFullIdent(firstChildDetailAST);

		String methodCall = fullIdent.getText();

		if (methodCall.startsWith("JSONUtil.")) {
			log(detailAST, _MSG_USE_JSON_UTIL_TO_STRING_1);
		}
	}

	private void _checkToJSONStringCalls(DetailAST detailAST) {
		if (!StringUtil.equals("toJSONString", getMethodName(detailAST))) {
			return;
		}

		List methodCallDetailASTList = getAllChildTokens(
			detailAST, true, TokenTypes.METHOD_CALL);

		if (methodCallDetailASTList.size() == 1) {
			DetailAST methodCallDetailAST = methodCallDetailASTList.get(0);

			DetailAST firstChildDetailAST = methodCallDetailAST.getFirstChild();

			if ((firstChildDetailAST != null) &&
				(firstChildDetailAST.getType() == TokenTypes.IDENT) &&
				_isJSONTypeMethodCall(
					detailAST, getMethodName(methodCallDetailAST))) {

				log(detailAST, _MSG_USE_JSON_UTIL_TO_STRING_2);
			}

			return;
		}

		if (ArrayUtil.contains(
				_VARIABLE_TYPE_NAMES,
				getVariableTypeName(
					detailAST, getVariableName(detailAST), false)) ||
			_isJSONUtilCall(detailAST)) {

			log(detailAST, _MSG_USE_JSON_UTIL_TO_STRING_2);
		}
	}

	private DetailAST _getMethodCallDetailAST(
		DetailAST assignDetailAST, DetailAST parentDetailAST) {

		DetailAST firstChildDetailAST = assignDetailAST.getFirstChild();

		DetailAST assignValueDetailAST = null;

		if (parentDetailAST.getType() == TokenTypes.EXPR) {
			assignValueDetailAST = firstChildDetailAST.getNextSibling();
		}
		else {
			assignValueDetailAST = firstChildDetailAST.getFirstChild();
		}

		if ((assignValueDetailAST != null) &&
			(assignValueDetailAST.getType() == TokenTypes.METHOD_CALL)) {

			return assignValueDetailAST;
		}

		return null;
	}

	private boolean _isJSONTypeMethodCall(
		DetailAST detailAST, String methodName) {

		if (Validator.isNull(methodName)) {
			return false;
		}

		DetailAST parentDetailAST = getParentWithTokenType(
			detailAST, TokenTypes.OBJBLOCK);

		List childDetailASTList = getAllChildTokens(
			parentDetailAST, false, TokenTypes.METHOD_DEF);

		for (DetailAST childDetailAST : childDetailASTList) {
			if (StringUtil.equals(getName(childDetailAST), methodName) &&
				ArrayUtil.contains(
					_VARIABLE_TYPE_NAMES, getTypeName(childDetailAST, false))) {

				return true;
			}
		}

		return false;
	}

	private boolean _isJSONUtilCall(DetailAST detailAST) {
		if (detailAST.getChildCount() == 0) {
			return false;
		}

		DetailAST firstChildDetailAST = detailAST.getFirstChild();

		if (firstChildDetailAST.getType() == TokenTypes.DOT) {
			FullIdent fullIdent = FullIdent.createFullIdent(
				firstChildDetailAST);

			String methodCall = fullIdent.getText();

			if (methodCall.startsWith("JSONUtil.")) {
				return true;
			}
		}

		return _isJSONUtilCall(firstChildDetailAST);
	}

	private static final String _MSG_USE_JSON_UTIL_PUT = "json.util.put.use";

	private static final String _MSG_USE_JSON_UTIL_PUT_ALL =
		"json.util.put.all.use";

	private static final String _MSG_USE_JSON_UTIL_TO_STRING_1 =
		"json.util.to.string.use.1";

	private static final String _MSG_USE_JSON_UTIL_TO_STRING_2 =
		"json.util.to.string.use.2";

	private static final String[] _VARIABLE_TYPE_NAMES = {
		"JSONArray", "JSONObject"
	};

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy