Search in sources :

Example 11 with N4JSPackageName

use of org.eclipse.n4js.workspace.utils.N4JSPackageName in project n4js by eclipse.

the class ProjectImportEnablingScope method computeImportType.

/**
 * Convenience method over
 * {@link ImportSpecifierUtil#computeImportType(QualifiedName, boolean, N4JSProjectConfigSnapshot)}
 */
private ModuleSpecifierForm computeImportType(QualifiedName name, N4JSProjectConfigSnapshot project) {
    final String firstSegment = name.getFirstSegment();
    final N4JSProjectConfigSnapshot targetProject = findProject(new N4JSPackageName(firstSegment), project, true);
    final boolean firstSegmentIsProjectName = targetProject != null;
    return ImportSpecifierUtil.computeImportType(name, firstSegmentIsProjectName, targetProject);
}
Also used : N4JSPackageName(org.eclipse.n4js.workspace.utils.N4JSPackageName) N4JSProjectConfigSnapshot(org.eclipse.n4js.workspace.N4JSProjectConfigSnapshot)

Example 12 with N4JSPackageName

use of org.eclipse.n4js.workspace.utils.N4JSPackageName in project n4js by eclipse.

the class ProjectImportEnablingScope method handleCollisions.

/**
 * Special case handling when we have a definition and a pure JS file in the scope. In such cases we return with the
 * description that corresponds to the definition file. Given several modules with the same name, there exists a
 * resolution only iff:
 * <ul>
 * <li/>There is a plain js module, and
 * <li/>An N4JSD module must be the corresponding definition module inside the corresponding definition project, and
 * <li/>An d.ts module must be the corresponding definition module inside the corresponding definition project
 * </ul>
 * In case both an N4JSD and a d.ts module exist, the n4jsd module is returned. Otherwise either the N4JSD or the
 * d.ts module is returned.
 */
private IEObjectDescription handleCollisions(List<IEObjectDescription> result, Map<IEObjectDescription, N4JSProjectConfigSnapshot> descriptionsToProject) {
    Set<String> considerExtensions = ImmutableSet.<String>builder().addAll(ALL_JS_FILE_EXTENSIONS).add(N4JSD_FILE_EXTENSION).add(DTS_FILE_EXTENSION).build();
    Map<String, IEObjectDescription> descr4Ext = new HashMap<>();
    Map<String, N4JSProjectConfigSnapshot> prj4Ext = new HashMap<>();
    for (IEObjectDescription res : result) {
        String ext = URIUtils.fileExtension(res.getEObjectURI());
        if (!considerExtensions.contains(ext)) {
            continue;
        }
        N4JSProjectConfigSnapshot prj = descriptionsToProject.get(res);
        if (descr4Ext.containsKey(ext)) {
            // return null due to conflict
            return null;
        }
        if (ext != null && prj != null) {
            descr4Ext.put(ext, res);
            prj4Ext.put(ext, prj);
        }
    }
    if (descr4Ext.size() < 2) {
        // return null due to missing project information
        return null;
    }
    // NOTE: the priority between .js/.cjs/.mjs we implement in the following loop based on the order in constant
    // ALL_JS_FILE_EXTENSIONS does not have an effect in practice, because conflicts between .js/.cjs/.mjs files are
    // resolved up front (see #removeSuperfluousPlainJsFiles() and its invocation in #getSingleElement()), meaning
    // we will always have only one of .js/.cjs/.mjs when reaching this point in the code:
    N4JSProjectConfigSnapshot jsProject = null;
    for (String jsFileExt : ALL_JS_FILE_EXTENSIONS) {
        N4JSProjectConfigSnapshot removed = prj4Ext.remove(jsFileExt);
        if (removed != null) {
            jsProject = removed;
        }
    }
    if (jsProject == null) {
        // return null due to missing implementation module
        return null;
    }
    Iterator<Entry<String, N4JSProjectConfigSnapshot>> iter = prj4Ext.entrySet().iterator();
    while (iter.hasNext()) {
        Entry<String, N4JSProjectConfigSnapshot> entry = iter.next();
        String ext = entry.getKey();
        N4JSProjectConfigSnapshot prj = entry.getValue();
        if (!Objects.equals(jsProject.getPathAsFileURI(), prj.getPathAsFileURI())) {
            // case both modules are in different projects: check here iff related
            switch(ext) {
                case N4JSD_FILE_EXTENSION:
                    if (prj.getType() != ProjectType.DEFINITION || !Objects.equals(prj.getDefinesPackage(), new N4JSPackageName(jsProject.getName()))) {
                        // return null due to conflict
                        return null;
                    }
                    break;
                case DTS_FILE_EXTENSION:
                    if (prj.getType() != ProjectType.PLAINJS || !prj.getName().endsWith("/" + jsProject.getPackageName())) {
                        // return null due to conflict
                        return null;
                    }
                    break;
                default:
            }
        } else {
        // case both modules are in same project: assume one being the definition of the other
        }
    }
    if (prj4Ext.size() == 1) {
        String dExt = prj4Ext.keySet().iterator().next();
        return descr4Ext.get(dExt);
    } else if (prj4Ext.size() == 2) {
        if (descr4Ext.containsKey(N4JSD_FILE_EXTENSION)) {
            // paranoia check - should always be true
            return descr4Ext.get(N4JSD_FILE_EXTENSION);
        }
        if (descr4Ext.containsKey(DTS_FILE_EXTENSION)) {
            // paranoia check - should always be true
            return descr4Ext.get(DTS_FILE_EXTENSION);
        }
    }
    return null;
}
Also used : Entry(java.util.Map.Entry) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) N4JSPackageName(org.eclipse.n4js.workspace.utils.N4JSPackageName) N4JSProjectConfigSnapshot(org.eclipse.n4js.workspace.N4JSProjectConfigSnapshot) IEObjectDescription(org.eclipse.xtext.resource.IEObjectDescription)

Example 13 with N4JSPackageName

use of org.eclipse.n4js.workspace.utils.N4JSPackageName in project n4js by eclipse.

the class ProjectCompareHelper method compareModules.

/**
 * Get the comparison for a module in a specific implementation specified by it's ID.
 *
 * @param module
 *            can be either Implementation or API
 * @param implementationID
 *            the current implementation to compare with
 *
 * @param includePolyfills
 *            {@code true} if polyfills should be considered as the part of the API and the implementation.
 *            Otherwise {@code false}.
 * @return a comparison between API and implementation with implementationID, or <code>null</code> if no project
 *         could be found, the module is not part of an API/IMPL ...
 */
public ProjectComparisonEntry compareModules(TModule module, N4JSPackageName implementationID, final boolean includePolyfills) {
    Resource resource = module.eResource();
    N4JSWorkspaceConfigSnapshot wc = workspaceAccess.getWorkspaceConfig(resource);
    N4JSProjectConfigSnapshot project = workspaceAccess.findProjectContaining(resource);
    if (project == null) {
        return null;
    }
    N4JSProjectConfigSnapshot implProject = null;
    N4JSProjectConfigSnapshot apiProject = null;
    TModule apiModule = null;
    TModule apiImplModule = null;
    if (project.getImplementationId() == null) {
        // this is NOT an implementation project, so assume we have the api
        // need to load the correct implementation. Since there might be multiple implementors
        ApiImplMapping mapping = ApiImplMapping.of(wc);
        implProject = mapping.getImpl(project.getN4JSPackageName(), implementationID);
        if (implProject == null) {
            // no implementation found.
            return null;
        }
        apiProject = project;
        apiModule = module;
        URI impUri = artifactHelper.findArtifact(implProject, apiModule.getQualifiedName(), Optional.of(N4JSGlobals.N4JS_FILE_EXTENSION));
        if (impUri != null) {
            IResourceDescriptions xtextIndex = workspaceAccess.getXtextIndex(module).orNull();
            IResourceDescription resourceDescription = xtextIndex != null ? xtextIndex.getResourceDescription(impUri) : null;
            if (resourceDescription != null) {
                apiImplModule = workspaceAccess.loadModuleFromIndex(module.eResource().getResourceSet(), resourceDescription, false);
            } else {
                if (logger.isDebugEnabled()) {
                    logger.debug("...ouch nothing in index for " + impUri);
                }
                Resource implResource = module.eResource().getResourceSet().getResource(impUri, true);
                apiImplModule = (TModule) implResource.getContents().get(1);
                // .get(1);
                if (logger.isDebugEnabled()) {
                    logger.debug("TModule loaded from Resource: " + apiImplModule);
                }
            }
        } else {
            // No implementation present.
            if (logger.isDebugEnabled()) {
                logger.debug("No implementation given. For " + apiModule.getQualifiedName());
            }
        }
    } else {
        // check that the implementation ID matches.
        if (implementationID.equals(new N4JSPackageName(project.getImplementationId()))) {
            implProject = project;
            apiImplModule = module;
            List<N4JSProjectConfigSnapshot> apiProjects = new ArrayList<>();
            for (ProjectReference apiProjectRef : implProject.getProjectDescription().getImplementedProjects()) {
                N4JSProjectConfigSnapshot currApiProject = wc.findProjectByID(apiProjectRef.getPackageName());
                if (currApiProject != null) {
                    apiProjects.add(currApiProject);
                }
            }
            labelA: for (N4JSProjectConfigSnapshot ap : apiProjects) {
                URI apiURI = artifactHelper.findArtifact(ap, apiImplModule.getQualifiedName(), Optional.of(N4JSGlobals.N4JSD_FILE_EXTENSION));
                if (apiURI != null) {
                    IResourceDescriptions xtextIndex = workspaceAccess.getXtextIndex(apiImplModule).orNull();
                    IResourceDescription resourceDescription = xtextIndex.getResourceDescription(apiURI);
                    if (resourceDescription != null) {
                        apiModule = workspaceAccess.loadModuleFromIndex(apiImplModule.eResource().getResourceSet(), resourceDescription, false);
                        if (apiModule != null)
                            break labelA;
                    }
                }
            }
        } else {
            return null;
        }
    }
    if (apiModule != null) {
        return compareModules(apiProject, apiModule, implProject, apiImplModule, includePolyfills);
    } else {
        // no apiModule --> this is not an implementation of API.
        return null;
    }
}
Also used : ProjectReference(org.eclipse.n4js.packagejson.projectDescription.ProjectReference) IResourceDescription(org.eclipse.xtext.resource.IResourceDescription) N4JSWorkspaceConfigSnapshot(org.eclipse.n4js.workspace.N4JSWorkspaceConfigSnapshot) N4JSPackageName(org.eclipse.n4js.workspace.utils.N4JSPackageName) N4JSProjectConfigSnapshot(org.eclipse.n4js.workspace.N4JSProjectConfigSnapshot) IResourceDescriptions(org.eclipse.xtext.resource.IResourceDescriptions) Resource(org.eclipse.emf.ecore.resource.Resource) ArrayList(java.util.ArrayList) TModule(org.eclipse.n4js.ts.types.TModule) URI(org.eclipse.emf.common.util.URI)

Example 14 with N4JSPackageName

use of org.eclipse.n4js.workspace.utils.N4JSPackageName in project n4js by eclipse.

the class ProjectCompareHelper method getImplementationID.

/**
 * Retrieves the implementation ID for an implementor of some API
 *
 * @param apiImplModule
 *            the implementor
 * @return implementation ID if applicable - unset if the parameter is not implementing an API or is itself from an
 *         API definition.
 */
public Optional<N4JSPackageName> getImplementationID(TModule apiImplModule) {
    N4JSProjectConfigSnapshot implProject = workspaceAccess.findProjectContaining(apiImplModule);
    String implId = implProject != null ? implProject.getImplementationId() : null;
    return implId != null ? Optional.of(new N4JSPackageName(implId)) : Optional.absent();
}
Also used : N4JSPackageName(org.eclipse.n4js.workspace.utils.N4JSPackageName) N4JSProjectConfigSnapshot(org.eclipse.n4js.workspace.N4JSProjectConfigSnapshot)

Example 15 with N4JSPackageName

use of org.eclipse.n4js.workspace.utils.N4JSPackageName in project n4js by eclipse.

the class ProjectCompareHelper method createComparison.

/**
 * First step in comparing API and implementation projects. This method will collect all API projects, the types
 * declared there and their members and relate them to the corresponding types and members in all available
 * implementation projects.
 * <p>
 * The second step of comparison is to compare an individual type/member to a corresponding type/member of a
 * particular implementation via method {@link #compareApiImpl(ProjectComparisonEntry, int)}.
 * <p>
 * Usually, this second step is performed lazily when method <code>#compareApiImpl()</code> is invoked; however, by
 * setting <code>fullCompare</code> to <code>true</code>, this is performed up-front here causing all results to be
 * stored in a cache in the entries, and then subsequent calls to <code>#compareApiImpl()</code> will just read from
 * that cache.
 * <p>
 * Returns <code>null</code> in case of error and adds human-readable error messages to the given list.
 */
public ProjectComparison createComparison(boolean fullCompare, List<String> addErrorMessagesHere) {
    final ResourceSet resourceSet = workspaceAccess.createResourceSet();
    final N4JSWorkspaceConfigSnapshot wc = workspaceAccess.getWorkspaceConfig(resourceSet);
    final IResourceDescriptions index = workspaceAccess.getXtextIndex(resourceSet).orNull();
    if (index == null) {
        addErrorMessagesHere.add("failed to create a new resource set with properly configured workspace configuration and index");
        return null;
    }
    final ApiImplMapping mapping = ApiImplMapping.of(wc);
    if (mapping.hasErrors()) {
        if (addErrorMessagesHere != null)
            addErrorMessagesHere.addAll(mapping.getErrorMessages());
        return null;
    }
    final List<N4JSPackageName> allImplIds = mapping.getAllImplIds();
    final int implCount = allImplIds.size();
    final ProjectComparison root = new ProjectComparison(allImplIds.toArray(new N4JSPackageName[implCount]));
    for (N4JSPackageName currApiId : mapping.getApiIds()) {
        final N4JSProjectConfigSnapshot currApi = mapping.getApi(currApiId);
        final N4JSProjectConfigSnapshot[] currImpls = new N4JSProjectConfigSnapshot[implCount];
        for (int idx = 0; idx < implCount; idx++) {
            final N4JSPackageName currImplId = allImplIds.get(idx);
            currImpls[idx] = mapping.getImpl(currApiId, currImplId);
        }
        createEntries(root, currApi, currImpls, resourceSet, index);
    }
    // compare all implementations in all entries and store in cache (if requested)
    if (fullCompare) {
        root.getAllEntries().forEach(currE -> {
            for (int implIdx = 0; implIdx < implCount; implIdx++) compareApiImpl(currE, implIdx);
        });
    }
    return root;
}
Also used : N4JSWorkspaceConfigSnapshot(org.eclipse.n4js.workspace.N4JSWorkspaceConfigSnapshot) N4JSPackageName(org.eclipse.n4js.workspace.utils.N4JSPackageName) IResourceDescriptions(org.eclipse.xtext.resource.IResourceDescriptions) N4JSProjectConfigSnapshot(org.eclipse.n4js.workspace.N4JSProjectConfigSnapshot) ResourceSet(org.eclipse.emf.ecore.resource.ResourceSet)

Aggregations

N4JSPackageName (org.eclipse.n4js.workspace.utils.N4JSPackageName)23 N4JSProjectConfigSnapshot (org.eclipse.n4js.workspace.N4JSProjectConfigSnapshot)9 Path (java.nio.file.Path)8 File (java.io.File)5 ArrayList (java.util.ArrayList)5 LinkedHashMap (java.util.LinkedHashMap)5 HashMap (java.util.HashMap)3 Entry (java.util.Map.Entry)3 Set (java.util.Set)3 IEObjectDescription (org.eclipse.xtext.resource.IEObjectDescription)3 Optional (com.google.common.base.Optional)2 FluentIterable (com.google.common.collect.FluentIterable)2 Multimap (com.google.common.collect.Multimap)2 Sets (com.google.common.collect.Sets)2 IOException (java.io.IOException)2 Files (java.nio.file.Files)2 FileTime (java.nio.file.attribute.FileTime)2 Collection (java.util.Collection)2 Collections (java.util.Collections)2 HashSet (java.util.HashSet)2