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

com.liferay.source.formatter.checkstyle.check.OSGiCommandsCheck Maven / Gradle / Ivy

There is a newer version: 1.0.739
Show newest version
/**
 * SPDX-FileCopyrightText: (c) 2023 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.petra.string.CharPool;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.StringUtil;

import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import com.puppycrawl.tools.checkstyle.utils.AnnotationUtil;

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

/**
 * @author Kevin Lee
 */
public class OSGiCommandsCheck 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;
		}

		DetailAST implementsClauseDetailAST = detailAST.findFirstToken(
			TokenTypes.IMPLEMENTS_CLAUSE);

		if (implementsClauseDetailAST == null) {
			return;
		}

		List implementedClassNames = getNames(
			implementsClauseDetailAST, false);

		if (!implementedClassNames.contains("OSGiCommands")) {
			return;
		}

		DetailAST objBlockDetailAST = detailAST.findFirstToken(
			TokenTypes.OBJBLOCK);

		if (objBlockDetailAST == null) {
			return;
		}

		List importNames = getImportNames(detailAST);

		if (!importNames.contains(
				"org.osgi.service.component.annotations.Component")) {

			return;
		}

		DetailAST annotationDetailAST = AnnotationUtil.getAnnotation(
			detailAST, "Component");

		if (annotationDetailAST == null) {
			return;
		}

		DetailAST annotationMemberValuePairDetailAST =
			getAnnotationMemberValuePairDetailAST(
				annotationDetailAST, "property");

		if (annotationMemberValuePairDetailAST == null) {
			return;
		}

		DetailAST annotationArrayInitDetailAST =
			annotationMemberValuePairDetailAST.findFirstToken(
				TokenTypes.ANNOTATION_ARRAY_INIT);

		if (annotationArrayInitDetailAST == null) {
			return;
		}

		List osgiCommandScopes = _getProperties(
			annotationArrayInitDetailAST, "osgi.command.scope");

		if (osgiCommandScopes.isEmpty() || (osgiCommandScopes.size() != 1)) {
			return;
		}

		_checkClassName(detailAST, osgiCommandScopes.get(0));

		List methodDefinitionDetailASTList = getAllChildTokens(
			objBlockDetailAST, false, TokenTypes.METHOD_DEF);

		methodDefinitionDetailASTList = ListUtil.filter(
			methodDefinitionDetailASTList,
			methodDefinitionDetailAST -> {
				DetailAST modifiersDetailAST =
					methodDefinitionDetailAST.findFirstToken(
						TokenTypes.MODIFIERS);

				return modifiersDetailAST.branchContains(
					TokenTypes.LITERAL_PUBLIC);
			});

		List osgiCommandFunctions = _getProperties(
			annotationArrayInitDetailAST, "osgi.command.function");

		_checkIncorrectPublicMethodName(
			methodDefinitionDetailASTList, osgiCommandFunctions);
		_checkMissingUnimplementedMethod(
			detailAST, methodDefinitionDetailASTList, osgiCommandFunctions);

		if (importNames.contains(
				"org.osgi.service.component.annotations.Reference")) {

			_checkVariableDeclaration(objBlockDetailAST);
		}
	}

	private void _checkClassName(DetailAST detailAST, String osgiCommandScope) {
		String className = getName(detailAST);

		if (!StringUtil.equalsIgnoreCase(
				className, osgiCommandScope + "OSGiCommands")) {

			log(detailAST, _MSG_INCORRECT_CLASS_NAME);
		}
	}

	private void _checkIncorrectPublicMethodName(
		List methodDefinitionDetailASTList,
		List osgiCommandFunctions) {

		for (DetailAST methodDefinitionDetailAST :
				methodDefinitionDetailASTList) {

			String methodName = getName(methodDefinitionDetailAST);

			if (osgiCommandFunctions.contains(methodName)) {
				continue;
			}

			log(methodDefinitionDetailAST, _MSG_INCORRECT_PUBLIC_METHOD_NAME);
		}
	}

	private void _checkMissingUnimplementedMethod(
		DetailAST detailAST, List methodDefinitionDetailASTList,
		List osgiCommandFunctions) {

		List methodNames = new ArrayList<>();

		for (DetailAST methodDefinitionDetailAST :
				methodDefinitionDetailASTList) {

			String methodName = getName(methodDefinitionDetailAST);

			if (methodNames.contains(methodName)) {
				continue;
			}

			methodNames.add(methodName);
		}

		for (String osgiCommandFunction : osgiCommandFunctions) {
			if (methodNames.contains(osgiCommandFunction)) {
				continue;
			}

			log(
				detailAST, _MSG_MISSING_IMPLEMENTED_COMMAND_FUNCTION,
				osgiCommandFunction);
		}
	}

	private void _checkVariableDeclaration(DetailAST detailAST) {
		List variableDefinitionDetailASTList = getAllChildTokens(
			detailAST, false, TokenTypes.VARIABLE_DEF);

		for (DetailAST variableDefinitionDetailAST :
				variableDefinitionDetailASTList) {

			if (!AnnotationUtil.containsAnnotation(
					variableDefinitionDetailAST, "Reference")) {

				continue;
			}

			String typeName = getTypeName(variableDefinitionDetailAST, false);

			if (!typeName.endsWith("OSGiCommands")) {
				continue;
			}

			log(variableDefinitionDetailAST, _MSG_AVOID_OSGI_REFERENCE);
		}
	}

	private List _getProperties(DetailAST detailAST, String name) {
		List osgiCommandProperties = new ArrayList<>();

		for (DetailAST expressionDetailAST :
				getAllChildTokens(detailAST, false, TokenTypes.EXPR)) {

			DetailAST firstChildDetailAST = expressionDetailAST.getFirstChild();

			if (firstChildDetailAST.getType() != TokenTypes.STRING_LITERAL) {
				continue;
			}

			String[] property = StringUtil.split(
				StringUtil.unquote(firstChildDetailAST.getText()),
				CharPool.EQUAL);

			if (!property[0].equals(name)) {
				continue;
			}

			osgiCommandProperties.add(property[1]);
		}

		return osgiCommandProperties;
	}

	private static final String _MSG_AVOID_OSGI_REFERENCE =
		"osgi.reference.avoid";

	private static final String _MSG_INCORRECT_CLASS_NAME =
		"class.name.incorrect";

	private static final String _MSG_INCORRECT_PUBLIC_METHOD_NAME =
		"public.method.name.incorrect";

	private static final String _MSG_MISSING_IMPLEMENTED_COMMAND_FUNCTION =
		"implemented.command.function.missing";

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy