/*******************************************************************************
* Copyright (c) 2017 Rogue Wave Software Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Rogue Wave Software Inc. - initial implementation
*******************************************************************************/
package org.eclipse.php.phpunit.model;
import java.text.MessageFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.dltk.ast.Modifiers;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.index2.search.ISearchEngine.MatchRule;
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.core.search.SearchEngine;
import org.eclipse.php.internal.core.documentModel.provisional.contenttype.ContentTypeIdForPHP;
import org.eclipse.php.internal.core.model.PHPModelAccess;
import org.eclipse.php.internal.core.project.PHPNature;
import org.eclipse.php.internal.ui.util.StatusInfo;
import org.eclipse.php.phpunit.PHPUnitMessages;
public class PHPUnitValidator {
public static final String CLASS_NAME_VALID_REGEXP = "[a-zA-Z_][a-zA-Z0-9_]*"; //$NON-NLS-1$
private static final IType[] EMPTY_TYPES = new IType[0];
public static String validateClassName(String className, final IProject project, final StatusInfo status) {
className = className.trim();
if (className.length() == 0) {
if (status != null) {
status.setError(PHPUnitMessages.PHPUnitValidator_Empty_Class_Name);
}
return className;
}
final Matcher matcher = Pattern.compile(CLASS_NAME_VALID_REGEXP).matcher(className);
if (!matcher.matches()) {
if (status != null) {
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Class_Invalid, className));
}
return className;
}
if (project != null) {
final IType[] typesByName = getTypesByName(className, project);
if (typesByName != null && typesByName.length > 0)
if (status != null)
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Class_Exists,
project.getName(), className));
}
return matcher.group();
}
/**
* @param className
* @param project
* @return
*/
private static IType[] getTypesByName(String className, final IProject project) {
final IScriptProject scriptProject = DLTKCore.create(project);
IDLTKSearchScope searchScope = SearchEngine.createSearchScope(scriptProject);
return PHPModelAccess.getDefault().findTypes(className, MatchRule.EXACT, 0,
Modifiers.AccInterface | Modifiers.AccNameSpace, searchScope, null);
}
public static IContainer validateContainer(final Object container) {
return validateContainer(container, false, null);
}
public static IContainer validateContainer(final Object container, final boolean validateProject) {
return validateContainer(container, validateProject, null);
}
public static IContainer validateContainer(final Object container, final boolean validateProject,
final StatusInfo status) {
String containerName;
if (container instanceof String) {
containerName = (String) container;
} else if (container instanceof IContainer) {
final IContainer theContainer = (IContainer) container;
containerName = theContainer.getFullPath().toOSString();
if (!theContainer.isAccessible())
if (status != null) {
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Not_Accessible,
new Object[] { containerName }));
}
} else {
if (status != null) {
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Not_Folder, container));
}
return null;
}
if (containerName.length() == 0) {
if (status != null) {
status.setError(PHPUnitMessages.PHPUnitValidator_Folder_Name_Empty);
}
return null;
}
final IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
final IPath containerPath = new Path(containerName);
IResource resource = workspaceRoot.findMember(containerPath);
if (resource == null) {
if (status != null) {
status.setError(
MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Folder_Not_Exists, containerName));
}
return null;
}
if (!(resource instanceof IContainer)) {
if (status != null) {
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Not_Folder, containerName));
}
return null;
}
if (validateProject) {
if (PHPUnitValidator.validateProject(resource.getProject(), status) == null) {
return null;
}
resource = workspaceRoot.findMember(containerPath);
if (resource == null || !resource.isAccessible()) {
if (status != null) {
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Folder_Not_Accessible,
containerName));
}
return null;
}
}
return (IContainer) resource;
}
public static IModelElement validateElement(final Object element, final IProject project,
final boolean validateProject, int elementType, final StatusInfo status) {
if (validateProject && validateProject(project, status) == null) {
return null;
}
if (element instanceof IModelElement) {
if (project == null) {
return null;
}
IModelElement modelElement = (IModelElement) element;
IScriptProject scriptProject = modelElement.getScriptProject();
if (scriptProject.getProject() != project) {
// validate class name
IDLTKSearchScope searchScope = SearchEngine.createSearchScope(scriptProject);
IType[] foundClassElementsToTest = PHPModelAccess.getDefault().findTypes(modelElement.getElementName(),
MatchRule.EXACT, 0, Modifiers.AccInterface, searchScope, null);
if (foundClassElementsToTest == null || foundClassElementsToTest.length < 1) {
if (status != null)
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Not_In_Project,
modelElement.getElementName(), project.getName()));
return null;
}
modelElement = foundClassElementsToTest[0];
}
return modelElement;
} else if (element instanceof String) {
if (project == null)
return null;
final String elementName = ((String) element).trim();
if (elementName.length() == 0) { // $NON-NLS-1$
if (status != null) {
status.setWarning(PHPUnitMessages.PHPUnitValidator_No_Element);
}
return null;
}
// validate class name
IScriptProject scriptProject = DLTKCore.create(project);
IDLTKSearchScope searchScope = SearchEngine.createSearchScope(scriptProject);
IModelElement[] foundClassElementsToTest = null;
if (elementType == IModelElement.TYPE) {
foundClassElementsToTest = PHPModelAccess.getDefault().findTypes(elementName, MatchRule.EXACT, 0,
Modifiers.AccInterface, searchScope, null);
} else {
foundClassElementsToTest = PHPModelAccess.getDefault().findMethods(elementName, MatchRule.PREFIX,
Modifiers.AccGlobal, 0, searchScope, null);
}
if (foundClassElementsToTest == null || foundClassElementsToTest.length == 0) {
if (status != null)
status.setWarning(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_No_Element_In_Project,
elementName, project.getName()));
return null;
} else if (foundClassElementsToTest.length > 1) {
if (status != null) {
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Multiple_Elements,
elementName, project.getName()));
return null;
}
}
return foundClassElementsToTest[0];
} else {
if (status != null)
status.setWarning(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Unknown_Element, element));
return null;
}
}
public static String validateFileName(String fileName, final IContainer container, final StatusInfo status) {
fileName = fileName.trim();
if (container == null) {
if (status != null) {
status.setError(PHPUnitMessages.PHPUnitValidator_No_Container);
}
return fileName;
}
if (fileName.length() == 0) {
if (status != null) {
status.setError(PHPUnitMessages.PHPUnitValidator_No_FileName);
}
return fileName;
}
if (container.findMember(new Path(fileName)) != null) {
if (status != null) {
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_File_Exists, fileName,
container.getName()));
}
return fileName;
}
final IContentType contentType = Platform.getContentTypeManager()
.getContentType(ContentTypeIdForPHP.ContentTypeID_PHP);
if (!contentType.isAssociatedWith(fileName)) {
if (status != null) {
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_File_Not_PHP, fileName));
}
return fileName;
}
return fileName;
}
public static IProject validateProject(final Object project) {
return validateProject(project, null);
}
public static IProject validateProject(final Object project, final StatusInfo status) {
final String projectName;
final IProject theProject;
if (project instanceof IProject) {
theProject = (IProject) project;
projectName = theProject.getName();
} else if (project instanceof String) {
projectName = (String) project;
final IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
theProject = workspaceRoot.getProject(projectName);
} else {
if (status != null) {
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Not_Project, project));
}
return null;
}
try {
if (!theProject.isAccessible()) {
if (status != null)
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Project_Not_Accessible,
theProject.getName()));
return null;
}
if (!theProject.hasNature(PHPNature.ID)) {
if (status != null) {
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Project_Not_PHP,
theProject.getName()));
}
return null;
}
} catch (final CoreException e) {
if (status != null) {
status.setError(
MessageFormat.format(PHPUnitMessages.PHPUnitValidator_No_Project, projectName, e.getMessage()));
}
}
return theProject;
}
public static IType[] validateTests(final IType[] tests, final IProject project, final boolean validateProject,
final StatusInfo status) {
if (validateProject && validateProject(project, status) == null) {
return EMPTY_TYPES;
}
if (project == null)
return EMPTY_TYPES;
if (tests == null) {
status.setWarning(
MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Folder_No_Suites, project.getName()));
return EMPTY_TYPES;
}
if (tests.length == 0) {
status.setWarning(PHPUnitMessages.PHPUnitValidator_No_Suites);
return EMPTY_TYPES;
}
final PHPUnitSearchEngine searchEngine = new PHPUnitSearchEngine(DLTKCore.create(project));
for (int i = 0; i < tests.length; ++i) {
final IResource resource = tests[i].getResource();
if (resource.getProject() != project) {
if (status != null) {
status.setError(MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Not_Exists,
tests[i].getElementName(), project.getName()));
}
return EMPTY_TYPES;
}
if (!searchEngine.isTest(tests[i])) {
status.setError(
MessageFormat.format(PHPUnitMessages.PHPUnitValidator_Not_Test, tests[i].getElementName()));
return EMPTY_TYPES;
}
}
return tests;
}
}