Search in sources :

Example 51 with IN4JSProject

use of org.eclipse.n4js.projectModel.IN4JSProject in project n4js by eclipse.

the class TestDiscoveryHelper method isTestable.

/**
 * Checks if the resource at the given location can be executed as a test. The location may point to an N4JS project
 * or a folder or file within an N4JS project.
 * <p>
 * This method is intended as a very first check to decide if the user should be given the option to launch a test
 * or not; for example, to enable or disable a "Run as test" context menu item). This method does not check all
 * details because many checks are better handled at later stages when meaningful error messages can be provided to
 * the user.
 */
public boolean isTestable(final URI location) {
    if (null == location) {
        return false;
    }
    if (isProject(location)) {
        // location points an N4JS project
        // --> must contain at least 1 source container of type "test"
        // (do *not* check if the folder contains test classes (for performance reasons and
        // to show better error messages; same behavior as in JUnit support in Eclipse))
        final IN4JSProject p = n4jsCore.create(location);
        return p.getSourceContainers().stream().anyMatch(IN4JSSourceContainer::isTest);
    } else {
        // then extract the fragment and check the location for the module.
        if (location.hasFragment()) {
            return isTestable(location.trimFragment());
        }
        // (2) location must lie in a source container of type "test"
        final IN4JSSourceContainer c = n4jsCore.findN4JSSourceContainer(location).orNull();
        if (c == null || !c.isTest())
            return false;
        // (3) if the location points to an n4js-file, it must contain at least one test class
        final ResourceSet resourceSet = n4jsCore.createResourceSet(Optional.of(c.getProject()));
        final IResourceDescriptions index = n4jsCore.getXtextIndex(resourceSet);
        final IResourceDescription rdesc = index.getResourceDescription(location);
        if (rdesc != null) {
            return stream(rdesc.getExportedObjectsByType(T_CLASS)).anyMatch(desc -> hasTestMethods(resourceSet, desc));
        } else {
            // to show better error messages; same behavior as in JUnit support in Eclipse))
            return true;
        }
    }
}
Also used : IResourceDescription(org.eclipse.xtext.resource.IResourceDescription) IN4JSProject(org.eclipse.n4js.projectModel.IN4JSProject) IResourceDescriptions(org.eclipse.xtext.resource.IResourceDescriptions) ResourceSet(org.eclipse.emf.ecore.resource.ResourceSet) IN4JSSourceContainer(org.eclipse.n4js.projectModel.IN4JSSourceContainer)

Example 52 with IN4JSProject

use of org.eclipse.n4js.projectModel.IN4JSProject in project n4js by eclipse.

the class RunnerFileBasedShippedCodeConfigurationHelper method configureFromFileSystem.

/**
 * Reconfigures provided run configuration in regards of {@link RunConfiguration#getExecModule()},
 * {@link RunConfiguration#getInitModules()} and {@link RunConfiguration#getCoreProjectPaths()} by plain using file
 * system access to the shipped code. Intended to be used in situations where proper workspace setup is not
 * available and run configurations created by default are lacking essential information.
 *
 * It is up to the caller to decide when it is appropriate to call this method.
 *
 * @param config
 *            the configuration to be reconfigured.
 */
public void configureFromFileSystem(RunConfiguration config) {
    Iterable<IN4JSProject> allShippedProjects = RunnerN4JSCore.getAllShippedProjects();
    IN4JSProject customRuntimeEnvironment = getCustomRuntimeEnvironment(config, allShippedProjects);
    reconfigure(config, allShippedProjects, customRuntimeEnvironment);
}
Also used : IN4JSProject(org.eclipse.n4js.projectModel.IN4JSProject)

Example 53 with IN4JSProject

use of org.eclipse.n4js.projectModel.IN4JSProject in project n4js by eclipse.

the class RunnerHelper method getProjectExtendedDepsAndApiImplMapping.

/**
 * Returns a mapping from all API projects among <code>dependencies</code> to their corresponding implementation
 * project for implementation ID <code>implementationId</code>.
 * <p>
 * Special cases: if there are no API projects among the dependencies, this method will return an empty map in
 * {@link ApiUsage#concreteApiImplProjectMapping} and {@link ApiUsage#implementationIdRequired}<code>==false</code>;
 * otherwise, if <code>implementationId</code> is <code>null</code>, then this method will assert that there exists
 * exactly one implementation for the API projects among the dependencies and use that (stored in
 * {@link ApiUsage#implementationId}).
 * <p>
 * Throws exception in case of error given <code>throwOnError==true</code>, never returns null.
 *
 * @param runtimeEnvironment
 *            active runtime environment.
 * @param moduleToRun
 *            what to run.
 * @param implementationId
 *            might be <code>null</code>
 * @param throwOnError
 *            if true fast fail in erroneous situations. Otherwise tries to proceed in a meaningful way. State can
 *            then be queried on the ApiUsage instance.
 *
 * @return result wrapped in an {@link ApiUsage} instance.
 */
// TODO this methods could require some cleanup after the concepts of API-Implementation mappings stabilized...
public ApiUsage getProjectExtendedDepsAndApiImplMapping(RuntimeEnvironment runtimeEnvironment, URI moduleToRun, String implementationId, boolean throwOnError) {
    final LinkedHashSet<IN4JSProject> deps = new LinkedHashSet<>();
    // 1) add project containing the moduleToRun and its direct AND indirect dependencies
    final Optional<? extends IN4JSProject> project = n4jsCore.findProject(moduleToRun);
    if (project.isPresent() == false) {
        throw new RuntimeException("can't obtain containing project for moduleToRun: " + moduleToRun);
    }
    recursiveDependencyCollector(project.get(), deps, new RecursionGuard<>());
    // TODO need to add not only REs but also RLs they provide
    // 2) add the runtime environment project, REs it extends and RLs provided
    final Optional<IN4JSProject> reProject = getCustomRuntimeEnvironmentProject(runtimeEnvironment);
    if (reProject.isPresent()) {
        IN4JSProject re = reProject.get();
        recursiveExtendedREsCollector(re, deps);
    } else {
    // IDE-1359: don't throw exception to make runners work without user-defined runtime environment
    // (will be changed later when library manager is available!)
    // throw new RuntimeException("can't obtain runtime environment project for " + moduleToRun2);
    }
    // TODO actually we would like to return the dependencies in load order:
    // - RuntimeEnvironment boot
    // - all RuntimeLibrary boots (take deps2 between RLs into account)
    // - all other deps2 (order does not matter they just needs to be on path later)
    // - project to be called
    // maybe some in order DFS or something above?
    // manually transform to list, or is this one ok?
    final ApiImplMapping apiImplMapping = ApiImplMapping.of(deps, n4jsCore.findAllProjects());
    if (apiImplMapping.hasErrors()) {
        if (throwOnError)
            throw new IllegalStateException("the workspace setup contains errors related to API / implementation projects (check manifests of related projects):\n    " + Joiner.on("\n    ").join(apiImplMapping.getErrorMessages()));
    }
    if (apiImplMapping.isEmpty()) {
        return ApiUsage.of(new ArrayList<>(deps), Collections.<IN4JSProject, IN4JSProject>emptyMap(), apiImplMapping);
    }
    // there must be exactly one implementation for the API projects in the workspace
    if (implementationId == null) {
        final List<String> allImplIds = apiImplMapping.getAllImplIds();
        if (allImplIds.size() != 1) {
            if (throwOnError) {
                throw new IllegalStateException("no implementationId specified while several are available in the workspace: " + allImplIds);
            } else {
                // back out, further processing not possible without implementations id.
                return ApiUsage.of(new ArrayList<>(deps), Collections.emptyMap(), apiImplMapping, true);
            }
        } else {
            implementationId = allImplIds.get(0);
        }
    }
    final Map<IN4JSProject, IN4JSProject> apiImplProjectMapping = new LinkedHashMap<>();
    // projectIds of projects without an implementation
    final List<String> missing = new ArrayList<>();
    for (IN4JSProject dep : deps) {
        if (dep != null) {
            final String depId = dep.getProjectId();
            if (depId != null && apiImplMapping.isApi(depId)) {
                // so: dep is an API project ...
                final IN4JSProject impl = apiImplMapping.getImpl(depId, implementationId);
                if (impl != null) {
                    // so: impl is the implementation project for dep for implementation ID 'implementationId'
                    apiImplProjectMapping.put(dep, impl);
                } else {
                    // bad: no implementation for dep for implementation ID 'implementationId'
                    missing.add(depId);
                }
            }
        }
    }
    if (!missing.isEmpty()) {
        if (throwOnError) {
            throw new IllegalStateException("no implementation for implementation ID \"" + implementationId + "\" found for the following projects: " + Joiner.on(", ").join(missing));
        }
    }
    // / #-#-#-#-#-#-#-#-#-#-#-#-#-#-#
    // IDEBUG-506 look for additional dependencies, pulled in from api-impl project not yet processed:
    HashSet<IN4JSProject> processedDepProjects = deps;
    LinkedHashSet<IN4JSProject> tobeInspectedApiImplProjects = new LinkedHashSet<>();
    apiImplProjectMapping.entrySet().forEach(p -> {
        IN4JSProject v = p.getValue();
        if (!processedDepProjects.contains(v))
            tobeInspectedApiImplProjects.add(v);
    });
    // Collect transitive mappings. Populate with original ones.
    final Map<IN4JSProject, IN4JSProject> joinedApiImplProjectMapping = new LinkedHashMap<>(apiImplProjectMapping);
    while (!tobeInspectedApiImplProjects.isEmpty()) {
        // compute dependencies if necessary
        LinkedHashSet<IN4JSProject> batchedPivotDependencies = new LinkedHashSet<>();
        RecursionGuard<URI> guard = new RecursionGuard<>();
        for (IN4JSProject pivotProject : tobeInspectedApiImplProjects) {
            recursiveDependencyCollector(pivotProject, batchedPivotDependencies, guard);
        }
        tobeInspectedApiImplProjects.clear();
        List<IN4JSProject> batchedPivotNewDepList = batchedPivotDependencies.stream().filter(p -> null != p && !processedDepProjects.contains(p)).collect(Collectors.toList());
        // new Api-mapping
        apiImplMapping.enhance(batchedPivotNewDepList, n4jsCore.findAllProjects());
        // go over new dependencies and decide:
        for (IN4JSProject pivNewDep : batchedPivotNewDepList) {
            final String depId = pivNewDep.getProjectId();
            if (apiImplMapping.isApi(depId)) {
                // API-mapping
                if (joinedApiImplProjectMapping.containsKey(pivNewDep)) {
                // already done.
                } else {
                    // put new entry
                    IN4JSProject pivImpl = apiImplMapping.getImpl(depId, implementationId);
                    if (null != pivImpl) {
                        joinedApiImplProjectMapping.put(pivNewDep, pivImpl);
                        tobeInspectedApiImplProjects.add(pivImpl);
                    } else {
                        missing.add(depId);
                    }
                }
            } else {
                // no API.
                if (!processedDepProjects.contains(pivNewDep)) {
                    // add to deps
                    processedDepProjects.add(pivNewDep);
                }
            }
        }
    }
    if (!missing.isEmpty()) {
        if (throwOnError) {
            throw new IllegalStateException("no implementation for implementation ID \"" + implementationId + "\" found for the following projects: " + Joiner.on(", ").join(missing));
        }
    }
    return ApiUsage.of(implementationId, new ArrayList<>(deps), apiImplProjectMapping, apiImplMapping, missing);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) BootstrapModule(org.eclipse.n4js.n4mf.BootstrapModule) URI(org.eclipse.emf.common.util.URI) Inject(com.google.inject.Inject) ResourceNameComputer(org.eclipse.n4js.utils.ResourceNameComputer) IN4JSCore(org.eclipse.n4js.projectModel.IN4JSCore) IN4JSSourceContainerAware(org.eclipse.n4js.projectModel.IN4JSSourceContainerAware) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) Strings(com.google.common.base.Strings) RunnerRegistry(org.eclipse.n4js.runner.extension.RunnerRegistry) N4JSGlobals(org.eclipse.n4js.N4JSGlobals) Optional(com.google.common.base.Optional) Map(java.util.Map) RecursionGuard(org.eclipse.n4js.utils.RecursionGuard) IRunnerDescriptor(org.eclipse.n4js.runner.extension.IRunnerDescriptor) RuntimeEnvironment(org.eclipse.n4js.runner.extension.RuntimeEnvironment) ApiImplMapping(org.eclipse.n4js.compare.ApiImplMapping) Path(java.nio.file.Path) LinkedHashSet(java.util.LinkedHashSet) Collections.emptyList(java.util.Collections.emptyList) Collection(java.util.Collection) IN4JSProject(org.eclipse.n4js.projectModel.IN4JSProject) Set(java.util.Set) Collectors(java.util.stream.Collectors) File(java.io.File) ProjectType(org.eclipse.n4js.n4mf.ProjectType) List(java.util.List) Lists.newArrayList(com.google.common.collect.Lists.newArrayList) IN4JSArchive(org.eclipse.n4js.projectModel.IN4JSArchive) AbstractSubGenerator(org.eclipse.n4js.generator.AbstractSubGenerator) Collections(java.util.Collections) FindArtifactHelper(org.eclipse.n4js.utils.FindArtifactHelper) Joiner(com.google.common.base.Joiner) ApiImplMapping(org.eclipse.n4js.compare.ApiImplMapping) ArrayList(java.util.ArrayList) Lists.newArrayList(com.google.common.collect.Lists.newArrayList) RecursionGuard(org.eclipse.n4js.utils.RecursionGuard) URI(org.eclipse.emf.common.util.URI) LinkedHashMap(java.util.LinkedHashMap) IN4JSProject(org.eclipse.n4js.projectModel.IN4JSProject)

Example 54 with IN4JSProject

use of org.eclipse.n4js.projectModel.IN4JSProject in project n4js by eclipse.

the class RunnerN4JSCore method getAllShippedProjects.

/**
 * Returns all shipped projects as iterable. Returned projects are stubs for real {@link N4JSProject}. They
 * implement the same API only to allow common utilities to calculate runner information for both real workspace
 * based projects and stubs returned here. All information is calculated from the file system on the fly, and is not
 * stored. Subsequent calls will result all information being computed once more.
 *
 * @return iterable of shipped code wrapped in {@link IN4JSProject} interface
 */
public static Iterable<IN4JSProject> getAllShippedProjects() {
    final RunnerTargetPlatformInstallLocationProvider locationProvider = new RunnerTargetPlatformInstallLocationProvider();
    final RunnerClasspathPackageManager manager = new RunnerClasspathPackageManager();
    final RunnerExternalLibraryWorkspace workspace = new RunnerExternalLibraryWorkspace(manager);
    final N4JSModel model = new N4JSModel(workspace, locationProvider);
    ShippedCodeAccess.getAllShippedPaths().forEach(path -> discoveProjects(path, workspace));
    // we need to collect projects provided by the workspace iterator into iterable instance to allow caller to make
    // multiple iterations over it. Note that just wrapping iterator into iterable (e.g. via
    // org.eclipse.xtext.xbase.lib.IteratorExtensions) does not work, i.e. it is just simple wrapping that allows
    // one iteration just like plain iterator.
    List<IN4JSProject> projects = new ArrayList<>();
    workspace.getAllProjectsLocations().forEachRemaining(location -> projects.add(model.getN4JSProject(location)));
    return projects;
}
Also used : IN4JSProject(org.eclipse.n4js.projectModel.IN4JSProject) ArrayList(java.util.ArrayList) N4JSModel(org.eclipse.n4js.internal.N4JSModel)

Example 55 with IN4JSProject

use of org.eclipse.n4js.projectModel.IN4JSProject in project n4js by eclipse.

the class RuntimeEnvironmentsHelper method recursiveCompatibleEnvironemntCollector.

/**
 * recursively searches given source container for provided runtime environments
 */
private void recursiveCompatibleEnvironemntCollector(IN4JSSourceContainerAware sourceContainer, Collection<String> collection, Predicate<IN4JSProject> predicate, List<IN4JSProject> allRuntimeEnv) {
    IN4JSProject project = (extractProject(sourceContainer));
    if (predicate.test(project)) {
        com.google.common.base.Optional<String> oExtendedProjectId = project.getExtendedRuntimeEnvironmentId();
        if (!oExtendedProjectId.isPresent()) {
            return;
        }
        String extendedProjectId = oExtendedProjectId.get();
        collection.add(extendedProjectId);
        allRuntimeEnv.stream().filter(p -> p.getProjectId().equals(extendedProjectId)).findFirst().ifPresent(exre -> recursiveCompatibleEnvironemntCollector(exre, collection, predicate, allRuntimeEnv));
    }
}
Also used : IN4JSProject(org.eclipse.n4js.projectModel.IN4JSProject)

Aggregations

IN4JSProject (org.eclipse.n4js.projectModel.IN4JSProject)93 URI (org.eclipse.emf.common.util.URI)32 Test (org.junit.Test)18 ArrayList (java.util.ArrayList)13 List (java.util.List)11 Inject (com.google.inject.Inject)9 Map (java.util.Map)9 IProject (org.eclipse.core.resources.IProject)9 IN4JSCore (org.eclipse.n4js.projectModel.IN4JSCore)9 Optional (com.google.common.base.Optional)7 File (java.io.File)7 Collection (java.util.Collection)7 HashSet (java.util.HashSet)7 ResourceSet (org.eclipse.emf.ecore.resource.ResourceSet)7 Set (java.util.Set)6 Collectors (java.util.stream.Collectors)6 IOException (java.io.IOException)5 IN4JSArchive (org.eclipse.n4js.projectModel.IN4JSArchive)5 IN4JSSourceContainer (org.eclipse.n4js.projectModel.IN4JSSourceContainer)5 FluentIterable.from (com.google.common.collect.FluentIterable.from)4