package com.redhat.ceylon.test.eclipse.plugin.launch; import static com.redhat.ceylon.test.eclipse.plugin.CeylonTestMessages.msg; import static com.redhat.ceylon.test.eclipse.plugin.CeylonTestPlugin.LAUNCH_CONFIG_ENTRIES_KEY; import static com.redhat.ceylon.test.eclipse.plugin.util.CeylonTestUtil.extractAnonymousClassIfRequired; import static com.redhat.ceylon.test.eclipse.plugin.util.CeylonTestUtil.getModule; import static com.redhat.ceylon.test.eclipse.plugin.util.CeylonTestUtil.getPackage; import static com.redhat.ceylon.test.eclipse.plugin.util.CeylonTestUtil.getProject; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.jface.viewers.TreePath; import com.redhat.ceylon.model.typechecker.model.Class; import com.redhat.ceylon.model.typechecker.model.Declaration; import com.redhat.ceylon.model.typechecker.model.Function; import com.redhat.ceylon.model.typechecker.model.Module; import com.redhat.ceylon.model.typechecker.model.Package; import com.redhat.ceylon.model.typechecker.model.Scope; import com.redhat.ceylon.test.eclipse.plugin.CeylonTestMessages; import com.redhat.ceylon.test.eclipse.plugin.util.MethodWithContainer; public class CeylonTestLaunchConfigEntry { private static final String TYPE_SEPARATOR = "="; private static final String PROJECT_SEPARATOR = ";"; private static final String PACKAGE_SEPARATOR = "::"; private static final String MEMBER_SEPARATOR = "."; public enum Type { PROJECT, MODULE, PACKAGE, CLASS, CLASS_LOCAL, METHOD, METHOD_LOCAL } public static CeylonTestLaunchConfigEntry build(IProject project, Type type, String modPkgDeclName) { CeylonTestLaunchConfigEntry entry = new CeylonTestLaunchConfigEntry(); entry.projectName = project.getName(); entry.type = type; entry.modPkgDeclName = modPkgDeclName; return entry; } public static CeylonTestLaunchConfigEntry buildFromTreePath(TreePath treePath) { Object firstSegment = treePath.getFirstSegment(); Object lastSegment = treePath.getLastSegment(); CeylonTestLaunchConfigEntry entry = new CeylonTestLaunchConfigEntry(); entry.projectName = ((IProject) firstSegment).getName(); if (lastSegment instanceof IProject) { entry.type = Type.PROJECT; } else if (lastSegment instanceof Module) { entry.type = Type.MODULE; entry.modPkgDeclName = ((Module) lastSegment).getNameAsString(); } else if (lastSegment instanceof Package) { entry.type = Type.PACKAGE; entry.modPkgDeclName = ((Package) lastSegment).getNameAsString(); } else if (lastSegment instanceof Class) { Class clazz = (Class) lastSegment; entry.type = clazz.isShared() ? Type.CLASS : Type.CLASS_LOCAL; entry.modPkgDeclName = clazz.getQualifiedNameString(); } else if (lastSegment instanceof Function) { Function method = (Function) lastSegment; entry.type = method.isShared() ? Type.METHOD : Type.METHOD_LOCAL; entry.modPkgDeclName = method.getQualifiedNameString(); } else if( lastSegment instanceof MethodWithContainer ) { MethodWithContainer methodWithContainer = (MethodWithContainer) lastSegment; entry.type = methodWithContainer.getMethod().isShared() ? Type.METHOD : Type.METHOD_LOCAL; entry.modPkgDeclName = methodWithContainer.getContainer().getQualifiedNameString() + "." + methodWithContainer.getMethod().getName(); } return entry; } public static List<CeylonTestLaunchConfigEntry> buildFromLaunchConfig(ILaunchConfiguration config) throws CoreException { List<CeylonTestLaunchConfigEntry> entries = new ArrayList<CeylonTestLaunchConfigEntry>(); List<String> attributes = config.getAttribute(LAUNCH_CONFIG_ENTRIES_KEY, new ArrayList<String>()); for (String attribute : attributes) { CeylonTestLaunchConfigEntry entry = buildFromLaunchConfigAttribute(attribute); entries.add(entry); } return entries; } private static CeylonTestLaunchConfigEntry buildFromLaunchConfigAttribute(String attribute) { CeylonTestLaunchConfigEntry entry = new CeylonTestLaunchConfigEntry(); int projectSeparatorIndex = attribute.indexOf(PROJECT_SEPARATOR); entry.projectName = attribute.substring(Type.PROJECT.name().length() + 1, projectSeparatorIndex); if (attribute.length() > projectSeparatorIndex + 1) { attribute = attribute.substring(projectSeparatorIndex + 1); int typeSeparatorIndex = attribute.indexOf(TYPE_SEPARATOR); entry.type = Type.valueOf(attribute.substring(0, typeSeparatorIndex)); entry.modPkgDeclName = attribute.substring(typeSeparatorIndex + 1); } else { entry.type = Type.PROJECT; } entry.validate(); return entry; } private static String buildLaunchConfigAttribute(CeylonTestLaunchConfigEntry entry) { StringBuilder attribute = new StringBuilder(); attribute.append(Type.PROJECT); attribute.append(TYPE_SEPARATOR); attribute.append(entry.getProjectName()); attribute.append(PROJECT_SEPARATOR); if (entry.getType() != Type.PROJECT) { attribute.append(entry.getType()); attribute.append(TYPE_SEPARATOR); attribute.append(entry.getModPkgDeclName()); } return attribute.toString(); } public static List<String> buildLaunchConfigAttributes(List<CeylonTestLaunchConfigEntry> entries) { List<String> attributes = new ArrayList<String>(); for (CeylonTestLaunchConfigEntry entry : entries) { attributes.add(buildLaunchConfigAttribute(entry)); } return attributes; } private Type type; private String projectName; private String moduleName; private String modPkgDeclName; private String errorMessage; public Type getType() { return type; } public String getProjectName() { return projectName; } public String getModuleName() { return moduleName; } public String getModPkgDeclName() { return modPkgDeclName; } public String getErrorMessage() { return errorMessage; } public boolean isValid() { return errorMessage == null; } public void validate() { errorMessage = null; IProject project = validateProject(); if( !isValid() || type == Type.PROJECT ) return; validateModule(project); if( !isValid() || type == Type.MODULE ) return; Package pkg = validatePackage(project); if(pkg != null) { moduleName = pkg.getModule().getNameAsString(); } if(!isValid() || type == Type.PACKAGE) { return; } validateDeclaration(pkg); } private void validateDeclaration(Package pkg) { String[] paths = parsePaths(); Scope scope = pkg; Declaration d = null; if( paths == null|| paths.length == 0 || paths.length > 2 ) { errorMessage = msg(CeylonTestMessages.errorCanNotFindDeclaration, modPkgDeclName, projectName); return; } d = scope.getMember(paths[0], null, false); d = extractAnonymousClassIfRequired(d); if (d instanceof Class) { scope = (Class) d; } if (paths.length == 2) { d = scope.getMember(paths[1], null, false); } if( !(d instanceof Class) && (type == Type.CLASS || type == Type.CLASS_LOCAL) ) { errorMessage = msg(CeylonTestMessages.errorCanNotFindDeclaration, modPkgDeclName, projectName); } if( !(d instanceof Function) && (type == Type.METHOD || type == Type.METHOD_LOCAL) ) { errorMessage = msg(CeylonTestMessages.errorCanNotFindDeclaration, modPkgDeclName, projectName); } } private IProject validateProject() { IProject project = getProject(projectName); if (project == null) { errorMessage = msg(CeylonTestMessages.errorCanNotFindProject, projectName); } return project; } private void validateModule(IProject project) { if (type == Type.MODULE) { Module module = getModule(project, modPkgDeclName); if (module == null) { errorMessage = msg(CeylonTestMessages.errorCanNotFindModule, modPkgDeclName, projectName); } } } private Package validatePackage(IProject project) { String pkgName = parsePackageName(); Package pkg = getPackage(project, pkgName); if (pkg == null) { errorMessage = msg(CeylonTestMessages.errorCanNotFindPackage, pkgName, projectName); } return pkg; } private String parsePackageName() { String pkgName = null; if (type == Type.PACKAGE) { pkgName = modPkgDeclName; } else if (type == Type.CLASS || type == Type.CLASS_LOCAL || type == Type.METHOD || type == Type.METHOD_LOCAL) { int pkgSeparatorIndex = modPkgDeclName.indexOf(PACKAGE_SEPARATOR); if (pkgSeparatorIndex != -1) { pkgName = modPkgDeclName.substring(0, pkgSeparatorIndex); } } return pkgName; } private String[] parsePaths() { String[] paths = new String[0]; int pkgSeparatorIndex = modPkgDeclName.indexOf(PACKAGE_SEPARATOR); if (pkgSeparatorIndex != -1) { String path = modPkgDeclName.substring(pkgSeparatorIndex + 2); paths = path.split("\\" + MEMBER_SEPARATOR); } return paths; } }