blob: 44dce4dc02a67bb906071973d09fc4602e24f34d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011-2012 Sierra Wireless 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:
* Sierra Wireless - initial API and implementation
*******************************************************************************/
package org.eclipse.koneki.ldt.core;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.dltk.compiler.env.IModuleSource;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IExternalSourceModule;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IParent;
import org.eclipse.dltk.core.IProjectFragment;
import org.eclipse.dltk.core.IScriptFolder;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.environment.EnvironmentPathUtils;
import org.eclipse.koneki.ldt.core.internal.Activator;
import org.eclipse.koneki.ldt.core.internal.buildpath.LuaExecutionEnvironmentBuildpathUtil;
/**
* Utility class for Lua
*/
public final class LuaUtils {
private LuaUtils() {
}
/**
* @return name of the module (without package qualifier) (no support of init.lua)
*/
public static String getModuleName(ISourceModule module) {
String moduleName = module.getElementName();
if (moduleName.endsWith(".lua")) { //$NON-NLS-1$
moduleName = moduleName.replaceFirst("\\.lua$", ""); //$NON-NLS-1$//$NON-NLS-2$
} else if (moduleName.endsWith(".doclua")) { //$NON-NLS-1$
moduleName = moduleName.replaceFirst("\\.doclua$", ""); //$NON-NLS-1$//$NON-NLS-2$
}
return moduleName;
}
/**
* @return name of the module (without package qualifier) (no support of init.lua)
*/
public static String getModuleName(final IModuleSource module) {
final IModelElement modelElement = module.getModelElement();
if (modelElement instanceof ISourceModule) {
return getModuleName((ISourceModule) modelElement);
} else {
return module.getFileName();
}
}
/**
* @return full name of a module with dot syntax (support init.lua case)<br>
*
* e.g. : socket.core
*/
public static String getModuleFullName(final IModuleSource module) {
final IModelElement modelElement = module.getModelElement();
if (modelElement instanceof ISourceModule) {
return getModuleFullName((ISourceModule) modelElement);
} else {
return module.getFileName();
}
}
/**
* @return full name of a module with dot syntax (support init.lua case) <br>
*
* e.g. : socket.core
*/
public static String getModuleFullName(final ISourceModule module) {
IPath path = getSourcePathRelativePath(module);
// replace file name by the module name
String moduleName = getModuleName(module);
path = path.removeLastSegments(1);
// handle the case of a package with a init module
if (path.segmentCount() == 0 || !"init".equals(moduleName)) { //$NON-NLS-1$
path = path.append(moduleName);
}
// build package prefix from the path
StringBuilder fullNameBuilder = new StringBuilder();
for (String segment : path.segments()) {
if (fullNameBuilder.length() > 0) {
fullNameBuilder.append("."); //$NON-NLS-1$
}
fullNameBuilder.append(segment);
}
return fullNameBuilder.toString();
}
/**
* @return the source path relative path of the given module
*/
public static IPath getSourcePathRelativePath(IModuleSource module) {
final IModelElement modelElement = module.getModelElement();
if (modelElement instanceof ISourceModule) {
return getSourcePathRelativePath((ISourceModule) modelElement);
} else {
return new Path(module.getFileName());
}
}
/**
* @return the source path relative path of the given module
*/
public static IPath getSourcePathRelativePath(ISourceModule module) {
String moduleName = module.getElementName();
// get prefix
IPath prefix = null;
if (module.getParent() instanceof IScriptFolder) {
prefix = getFolderSourcePathRelativePath((IScriptFolder) module.getParent());
}
if (prefix != null)
return prefix.append(moduleName);
else
return new Path(moduleName);
}
/*
* @return the source folder full name with module dot syntax
*/
private static IPath getFolderSourcePathRelativePath(final IScriptFolder folder) {
if (!folder.isRootFolder()) {
// get folder name
final String folderName = folder.getElementName();
// get prefix
final IModelElement parent = folder.getParent();
IPath prefix = null;
if (parent instanceof IScriptFolder) {
prefix = getFolderSourcePathRelativePath((IScriptFolder) parent);
}
if (prefix != null)
return prefix.append(folderName);
else
return new Path(folderName);
}
return null;
}
/**
* @return the {@link IModuleSource} from full name with module dot syntax
*/
public static IModuleSource getModuleSource(final String name, final IScriptProject project) {
if (project == null && name == null || name.isEmpty())
return null;
// search in all source path.
IProjectFragment[] allProjectFragments;
try {
allProjectFragments = project.getAllProjectFragments();
for (final IProjectFragment projectFragment : allProjectFragments) {
final IModuleSource moduleSource = getModuleSource(name, projectFragment);
if (moduleSource != null)
return moduleSource;
}
} catch (final ModelException e) {
Activator.logError(MessageFormat.format("Unable to find module: {0}.", name), e); //$NON-NLS-1$
return null;
}
return null;
}
/*
* @return the {@link IModuleSource} from full name with module dot syntax
*/
private static IModuleSource getModuleSource(final String name, final IParent parent) throws ModelException {
final IModelElement[] children = parent.getChildren();
for (final IModelElement child : children) {
if (child instanceof IModuleSource) {
if (name.equals(getModuleFullName((IModuleSource) child))) {
return (IModuleSource) child;
}
} else if (child instanceof IParent) {
final IModuleSource moduleSource = getModuleSource(name, (IParent) child);
if (moduleSource != null)
return moduleSource;
}
}
return null;
}
/**
* @return the {@link ISourceModule} from full name with module dot syntax
*/
public static ISourceModule getSourceModule(final String name, final IScriptProject project) {
final IModuleSource moduleSource = getModuleSource(name, project);
if (moduleSource instanceof ISourceModule) {
return (ISourceModule) moduleSource;
}
return null;
}
/**
* @return the {@link IModuleSource} from Absolute local file URI
*/
public static IModuleSource getModuleSourceFromAbsoluteURI(final URI absolutepath, final IScriptProject project) {
if (project == null || absolutepath == null)
return null;
final ISourceModule sourceModule = getSourceModuleFromAbsoluteURI(absolutepath, project);
if (sourceModule instanceof IModuleSource) {
return (IModuleSource) sourceModule;
}
return null;
}
/**
* @return the {@link ISourceModule} from Absolute local file URI
*/
public static ISourceModule getSourceModuleFromAbsoluteURI(final URI absolutepath, final IScriptProject project) {
if (project == null || absolutepath == null)
return null;
// search in all source path.
IProjectFragment[] allProjectFragments;
try {
allProjectFragments = project.getAllProjectFragments();
for (final IProjectFragment projectFragment : allProjectFragments) {
final ISourceModule moduleSource = getSourceModuleFromAbsolutePath(absolutepath, projectFragment);
if (moduleSource != null)
return moduleSource;
}
} catch (final ModelException e) {
Activator.logError(MessageFormat.format("Unable to find module: {0}.", absolutepath), e); //$NON-NLS-1$
return null;
}
return null;
}
/*
* @return the {@link ISourceModule} from Absolute local file URI and a parent
*/
private static ISourceModule getSourceModuleFromAbsolutePath(final URI absolutepath, final IParent parent) throws ModelException {
final IModelElement[] children = parent.getChildren();
for (final IModelElement child : children) {
if (child instanceof ISourceModule) {
if (URIUtil.sameURI(absolutepath, getModuleAbsolutePath((ISourceModule) child))) {
return (ISourceModule) child;
}
} else if (child instanceof IParent) {
final ISourceModule moduleSource = getSourceModuleFromAbsolutePath(absolutepath, (IParent) child);
if (moduleSource != null)
return moduleSource;
}
}
return null;
}
/**
* @return Absolute local file URI of a module source
*/
public static URI getModuleAbsolutePath(final ISourceModule module) {
if (module instanceof IExternalSourceModule) {
String path = EnvironmentPathUtils.getLocalPath(module.getPath()).toString();
if (path.length() != 0 && path.charAt(0) != '/') {
path = '/' + path;
}
try {
return new URI("file", "", path, null); //$NON-NLS-1$ //$NON-NLS-2$
} catch (final URISyntaxException e) {
final String message = MessageFormat.format("Unable to get file uri for external module : {0}.", module.getPath()); //$NON-NLS-1$
Activator.logWarning(message, e);
}
} else {
if (module.getResource() != null)
return module.getResource().getLocationURI();
}
return null;
}
/**
* @return the list of direct project dependencies
* @throws ModelException
*/
public static List<IScriptProject> getDependencies(final IScriptProject project) throws ModelException {
final ArrayList<IScriptProject> result = new ArrayList<IScriptProject>();
// check in all project fragments
final IProjectFragment[] projectFragments = project.getAllProjectFragments();
for (int i = 0; i < projectFragments.length; i++) {
final IProjectFragment projectFragment = projectFragments[i];
if (isProjectDependencyFragment(project, projectFragment)) {
final IScriptProject currentScriptProject = projectFragment.getScriptProject();
result.add(currentScriptProject);
}
}
return result;
}
public static boolean isProjectDependencyFragment(final IScriptProject project, final IProjectFragment projectFragment) throws ModelException {
final IScriptProject fragmentProject = projectFragment.getScriptProject();
if (fragmentProject != null && fragmentProject != project) {
return (!projectFragment.isArchive() && !projectFragment.isBinary() && !projectFragment.isExternal());
} else {
return false;
}
}
public static boolean isExecutionEnvironmentFragment(final IProjectFragment projectFragment) throws ModelException {
final IBuildpathEntry rawBuildpathEntry = projectFragment.getRawBuildpathEntry();
return (rawBuildpathEntry != null && LuaExecutionEnvironmentBuildpathUtil.isValidExecutionEnvironmentBuildPath(rawBuildpathEntry.getPath()));
}
public enum ProjectFragmentFilter {
EXECUTION_ENVIRONMENT, DEPENDENT_PROJECT, ARCHIVE
}
private static List<IProjectFragment> getProjectFragments(final IScriptProject project, EnumSet<ProjectFragmentFilter> filter,
final IProgressMonitor monitor) throws ModelException {
ArrayList<IProjectFragment> filteredProjecFragment = new ArrayList<IProjectFragment>();
// filter project fragment
final IProjectFragment[] projectFragments = project.getAllProjectFragments();
final SubMonitor filteredLoopMonitor = SubMonitor.convert(monitor, projectFragments.length);
for (int i = 0; i < projectFragments.length && !monitor.isCanceled(); i++) {
final IProjectFragment projectFragment = projectFragments[i];
if (isProjectDependencyFragment(project, projectFragment)) {
if (filter.contains(ProjectFragmentFilter.DEPENDENT_PROJECT))
filteredProjecFragment.add(projectFragment);
} else if (isExecutionEnvironmentFragment(projectFragment)) {
if (filter.contains(ProjectFragmentFilter.EXECUTION_ENVIRONMENT))
filteredProjecFragment.add(projectFragment);
} else if (projectFragment.isArchive()) {
if (filter.contains(ProjectFragmentFilter.ARCHIVE))
filteredProjecFragment.add(projectFragment);
} else {
filteredProjecFragment.add(projectFragment);
}
filteredLoopMonitor.worked(1);
}
return filteredProjecFragment;
}
/**
* @since 1.1
*/
public static void visitRootSourceFolder(final IScriptProject project, EnumSet<ProjectFragmentFilter> filter,
final IProjectSourceRootFolderVisitor2 visitor, final IProgressMonitor monitor) throws CoreException {
visitRootSourceFolder(project, filter, (Object) visitor, monitor);
}
/**
* Enable to perform operation in Root source folders
*
* @deprecated Use visitRootSourceFolder(IScriptProject, EnumSet<ProjectFragmentFilter>, IProjectSourceRootFolderVisitor2, IProgressMonitor)
* instead.
* */
public static void visitRootSourceFolder(final IScriptProject project, EnumSet<ProjectFragmentFilter> filter,
final IProjectSourceRootFolderVisitor visitor, final IProgressMonitor monitor) throws CoreException {
visitRootSourceFolder(project, filter, (Object) visitor, monitor);
}
@SuppressWarnings("deprecation")
private static void visitRootSourceFolder(final IScriptProject project, EnumSet<ProjectFragmentFilter> filter, final Object visitor,
final IProgressMonitor monitor) throws CoreException {
SubMonitor subMonitor = SubMonitor.convert(monitor, 10);
// get filtered project fragments
List<IProjectFragment> filteredProjecFragments = getProjectFragments(project, filter, subMonitor.newChild(1));
// visit fragment
final SubMonitor visitLoopMonitor = subMonitor.newChild(9).setWorkRemaining(filteredProjecFragments.size());
for (IProjectFragment projectFragment : filteredProjecFragments) {
if (monitor.isCanceled())
return;
IPath absolutePathFromModelElement = getAbsolutePathFromModelElement(projectFragment);
SubMonitor subMonitor2 = visitLoopMonitor.newChild(1);
if (visitor instanceof IProjectSourceRootFolderVisitor2) {
((IProjectSourceRootFolderVisitor2) visitor).processSourceRootFolder(projectFragment, absolutePathFromModelElement, subMonitor2);
} else if (visitor instanceof IProjectSourceRootFolderVisitor) {
((IProjectSourceRootFolderVisitor) visitor).processSourceRootFolder(absolutePathFromModelElement, subMonitor2);
}
}
}
/**
* @since 1.1
*/
public static void visitSourceFiles(final IScriptProject project, EnumSet<ProjectFragmentFilter> filter, final IProjectSourceVisitor2 visitor,
final IProgressMonitor monitor) throws CoreException {
visitSourceFiles(project, filter, (Object) visitor, monitor);
}
/**
* Enable to perform operation in all files and directories in project fragments source directories
*
* @deprecated Use visitSourceFiles(IScriptProject, EnumSet<ProjectFragmentFilter>, IProjectSourceVisitor2, IProgressMonitor) instead
* */
public static void visitSourceFiles(final IScriptProject project, EnumSet<ProjectFragmentFilter> filter, final IProjectSourceVisitor visitor,
final IProgressMonitor monitor) throws CoreException {
visitSourceFiles(project, filter, (Object) visitor, monitor);
}
private static void visitSourceFiles(final IScriptProject project, EnumSet<ProjectFragmentFilter> filter, final Object visitor,
final IProgressMonitor monitor) throws CoreException {
SubMonitor subMonitor = SubMonitor.convert(monitor, 10);
// get filtered project fragments
List<IProjectFragment> filteredProjecFragments = getProjectFragments(project, filter, subMonitor.newChild(1));
// visit fragment
final SubMonitor visitLoopMonitor = subMonitor.newChild(9).setWorkRemaining(filteredProjecFragments.size());
for (IProjectFragment projectFragment : filteredProjecFragments) {
if (monitor.isCanceled())
return;
visitSourceFiles(projectFragment, visitor, visitLoopMonitor.newChild(1), Path.EMPTY);
}
}
@SuppressWarnings("deprecation")
private static void visitSourceFiles(final IParent parent, final Object visitor, final IProgressMonitor monitor, final IPath currentPath)
throws CoreException {
final IModelElement[] children = parent.getChildren();
SubMonitor subMonitor = SubMonitor.convert(monitor, children.length);
for (int i = 0; i < children.length && !monitor.isCanceled(); i++) {
final IModelElement modelElement = children[i];
if (modelElement instanceof ISourceModule) {
/*
* Support local module
*/
IPath absolutePath = getAbsolutePathFromModelElement(modelElement);
String charset = getCharsetOfModelElement(modelElement);
final IPath relativeFilePath = currentPath.append(absolutePath.lastSegment());
if (visitor instanceof IProjectSourceVisitor2) {
((IProjectSourceVisitor2) visitor).processFile((ISourceModule) modelElement, absolutePath, relativeFilePath, charset,
subMonitor.newChild(1));
} else if (visitor instanceof IProjectSourceVisitor) {
((IProjectSourceVisitor) visitor).processFile(absolutePath, relativeFilePath, charset, subMonitor.newChild(1));
}
} else if (modelElement instanceof IScriptFolder) {
/*
* Support source folder
*/
final IScriptFolder innerSourceFolder = (IScriptFolder) modelElement;
// Do not notify interface for Source folders
if (!innerSourceFolder.isRootFolder()) {
IPath absolutePath = getAbsolutePathFromModelElement(modelElement);
final IPath newPath = currentPath.append(innerSourceFolder.getElementName());
if (visitor instanceof IProjectSourceVisitor2) {
((IProjectSourceVisitor2) visitor).processDirectory(innerSourceFolder, absolutePath, newPath, subMonitor.newChild(1));
} else if (visitor instanceof IProjectSourceVisitor) {
((IProjectSourceVisitor) visitor).processDirectory(absolutePath, newPath, subMonitor.newChild(1));
}
visitSourceFiles(innerSourceFolder, visitor, subMonitor.newChild(1), newPath);
} else {
// Deal with sub elements
visitSourceFiles(innerSourceFolder, visitor, subMonitor.newChild(1), Path.EMPTY);
}
}
}
}
private static IPath getAbsolutePathFromModelElement(final IModelElement modelElement) throws CoreException {
final IResource resource = modelElement.getResource();
if (resource != null) {
return resource.getLocation();
}
final IPath folderPath = modelElement.getPath();
if (EnvironmentPathUtils.isFull(folderPath)) {
return EnvironmentPathUtils.getLocalPath(folderPath);
}
final String message = MessageFormat.format("Unable to get absolute location for {0}.", modelElement.getElementName()); //$NON-NLS-1$
final Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, message);
throw new CoreException(status);
}
private static String getCharsetOfModelElement(final IModelElement modelElement) throws CoreException {
final IResource resource = modelElement.getResource();
if (resource instanceof IFile) {
final IFile file = (IFile) resource;
return file.getCharset();
}
return Charset.defaultCharset().toString();
}
/**
* @return all Open Lua project in the workspace
*/
public static final IProject[] getLuaProjects() {
List<IProject> luaProjects = new LinkedList<IProject>();
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for (IProject iProject : projects) {
try {
if (iProject.isAccessible() && iProject.hasNature(LuaNature.ID)) {
luaProjects.add(iProject);
}
} catch (CoreException e) {
// must not append
Activator.logWarning("Unexcepted error when collecting Lua project", e); //$NON-NLS-1$
}
}
return luaProjects.toArray(new IProject[luaProjects.size()]);
}
public static boolean isLuaProject(IProject project) {
try {
return project.hasNature(LuaNature.ID);
} catch (CoreException e) {
// must not append
Activator.logWarning("Unexcepted error when checking if project is a Lua project", e); //$NON-NLS-1$
}
return false;
}
/**
* @since 1.2
*/
public static IPath getLuaExecutionEnvironmentPath(IScriptProject project) {
try {
IBuildpathEntry[] rawBuildpath = project.getRawBuildpath();
for (IBuildpathEntry bpe : rawBuildpath) {
IPath path = bpe.getPath();
if (LuaExecutionEnvironmentBuildpathUtil.isLuaExecutionEnvironmentContainer(path)) {
return path;
}
}
} catch (ModelException e) {
Activator.logWarning(
String.format("Unexcepted error when getting Lua Execution environement for project %s", project.getElementName()), e); //$NON-NLS-1$
}
return null;
}
}